错误:NG0301:未找到名称“ngForm”导出

问题描述 投票:0回答:4

我是角度的初学者。我正在使用 Jasmine 测试我的代码,但遇到一些错误。我尝试根据我的知识导入所有内容。这些是我面临的错误:

  1. 错误:NG0301:未找到名称“ngForm”导出!
  2. 期望未定义为真。

此外,就功能而言,代码在浏览器中运行良好,但我在茉莉花隔离测试中遇到此错误。我该如何解决这些问题?

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';

import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';

import {FormsModule } from '@angular/forms';
import { BookRideComponent } from './book-ride/book-ride.component';
import { SortPipe } from './sort.pipe';
import { CustomPipeComponent } from './custom-pipe/custom-pipe.component';
import { CustpipeComponent } from './custpipe/custpipe.component';
import { RideFilterPipePipe } from './ride-filter-pipe.pipe';
import { ReactFormComponent } from './react-form/react-form.component';
import { TemplateDrivenFormComponent } from './template-driven-form/template-driven-form.component';
import { EmailValidator } from './template-driven-form/emailValidator';

@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    BookRideComponent,
    CustomPipeComponent,
    SortPipe,
    CustpipeComponent,
    RideFilterPipePipe,
    ReactFormComponent,
    TemplateDrivenFormComponent,
    EmailValidator
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    ReactiveFormsModule      
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.spec.ts

import { TestBed } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';

describe('AppComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [
        FormsModule,      
        RouterTestingModule,
        ReactiveFormsModule
      ],
      declarations: [
        AppComponent
      ],
    }).compileComponents();
  });

  it('should create the app', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.componentInstance;
    expect(app).toBeTruthy();
  });

  it(`should have as title 'carpool'`, () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.componentInstance;
    expect(app.title).toEqual('carpool');
  });

  it('should render title', () => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.nativeElement as HTMLElement;
    expect(compiled.querySelector('.content span')?.textContent).toContain('carpool app is running!');
  });
});

模板驱动-form.component.html

<div [hidden]="submitted">

<form (ngSubmit)="onSubmit()" #courseForm="ngForm" [ngFormOptions]="{updateOn:'blur'}">
    <div class="form-group">
        <label>id</label>
        <input type="text" class="form-control" required [(ngModel)]="course.courseId" name="id" #id="ngModel">
        <div [hidden]="id.valid || id.pristine" class="alert alert-danger">
            <p>*required</p>
        </div>
    </div>
    <div class="form-group">
        <label>Name</label>
        <input type="text" class="form-control" required [(ngModel)]="course.courseName" name="name" minlength="4" #name="ngModel">
        <div class="alert alert-danger" *ngIf="name.touched && !name.valid">
            <div *ngIf="name.errors && name.errors['required']">First Name is required.</div>
            <div *ngIf="name.errors && name.errors['minlength']">First Name is minimum {{ name.errors && name.errors['minlength'].requiredLength }} character.</div>
        </div>
    </div>
    
    <div class="form-group">
        <label>Duration</label>
        <input type="text" class="form-control" required [(ngModel)]="course.duration" name="duration" #duration="ngModel">
        <div [hidden]="duration.valid || duration.pristine" class="alert alert-danger">
            <p>*required</p>
        </div>
    </div>
    <div class="form-group">
        <label>Email</label>
      <!-- <input  type="text"  class="form-control" required ngModel name="firstName" #firstName="ngModel" id="firstName">
      <div class="alert alert-danger" *ngIf="firstName.touched && !firstName.valid">
          <div *ngIf="firstName.errors && firstName.errors['required']">Email is required.</div>
      </div> -->
        <input type="text" class="form-control" required [(ngModel)]="course.email" name="email" #email="ngModel" validateEmail>
        <div *ngIf="email.errors && (email.dirty || email.touched)" class="alert alert-danger">
            <p [hidden]="!email.errors['required']">*required</p>
            <p [hidden]="!email.errors['emailInvalid']">{{email.errors['emailInvalid']}}</p>
        </div>
    </div>
    <button type="submit" class="btn btn-primary" [disabled]="!courseForm.form.valid">Submit</button>
    <button type="reset" class="btn btn-primary" (click)="courseForm.reset()">Reset</button>
</form>

</div>
<div [hidden]="!submitted">
    <p>Course ID: {{course.courseId}}</p>
    <p>Course Name: {{course.courseName}}</p>
    <p>Course Duration: {{course.duration}}</p>
    <p>Course Email: {{course.email}}</p>
</div>

模板驱动的form.component.ts

import { Component, OnInit } from '@angular/core';
import { course } from '../course';

@Component({
  selector: 'app-template-driven-form',
  templateUrl: './template-driven-form.component.html',
  styleUrls: ['./template-driven-form.component.css']
})
export class TemplateDrivenFormComponent implements OnInit {

  course: course=new course(1, 'Angular','5 days', '[email protected]');
  submitted=false;
  constructor() { }

  ngOnInit(): void {
  }

  onSubmit() {
    this.submitted=true;
  }

}

模板驱动的form.component.spec.ts*


import { ComponentFixture, TestBed } from '@angular/core/testing';

import { TemplateDrivenFormComponent } from './template-driven-form.component';

describe('TemplateDrivenFormComponent', () => {
  let component: TemplateDrivenFormComponent;
  let fixture: ComponentFixture<TemplateDrivenFormComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ TemplateDrivenFormComponent ]
    })
    .compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(TemplateDrivenFormComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});
javascript angular angularjs typescript
4个回答
8
投票

我怀疑你现在已经弄清楚了,但是在你的 .spec 文件中你想将 FormsModule 添加到你的导入中:

import { FormsModule } from '@angular/forms';

...

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [ FormsModule ], // <-- here
      declarations: [ TemplateDrivenFormComponent ]
    })

1
投票

您必须在 template-driven-form.component.spec 中导入反应式表单模块配置

configureTestingModule

你需要在每次测试中导入你需要的所有东西,所以在app.component.spec中也导入reactiveformsmodule并不重要


1
投票

我也遇到了完全相同的问题。就我而言,我必须导入 ReactiveFormsModule,而不是 FormsModule。因此“template-driven-form.component.spec.ts”中的解决方案如下所示:

import { ReactiveFormsModule } from '@angular/forms';
...

describe('TemplateDrivenFormComponent', () => {

  beforeEach(waitForAsync(() => {
    ...
    TestBed.configureTestingModule({
      declarations: [
        TemplateDrivenFormComponent
      ],
      imports: [
        ReactiveFormsModule,
        ...
      ]
  });

0
投票

对我来说,ReactiveFormsModule 而不是 FormMudule 效果很好。

© www.soinside.com 2019 - 2024. All rights reserved.