Home > Software design >  Error: NG0301: Export of name 'ngForm' not found
Error: NG0301: Export of name 'ngForm' not found

Time:02-24

I am a beginner at angular. I am testing my code using Jasmine but I am getting some errors. I have tried to import everything as per my knowledge. These are the errors that I am facing:

  1. Error: NG0301: Export of name 'ngForm' not found!
  2. Expected undefined to be truthy.

Also, the code is working fine in the browser in terms of functionality yet I am getting this error in jasmine isolate testing. How can I solve these issues?

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!');
  });
});

template-driven-form.component.html

<div [hidden]="submitted">

<form (ngSubmit)="onSubmit()" #courseForm="ngForm" [ngFormOptions]="{updateOn:'blur'}">
    <div >
        <label>id</label>
        <input type="text"  required [(ngModel)]="course.courseId" name="id" #id="ngModel">
        <div [hidden]="id.valid || id.pristine" >
            <p>*required</p>
        </div>
    </div>
    <div >
        <label>Name</label>
        <input type="text"  required [(ngModel)]="course.courseName" name="name" minlength="4" #name="ngModel">
        <div  *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 >
        <label>Duration</label>
        <input type="text"  required [(ngModel)]="course.duration" name="duration" #duration="ngModel">
        <div [hidden]="duration.valid || duration.pristine" >
            <p>*required</p>
        </div>
    </div>
    <div >
        <label>Email</label>
      <!-- <input  type="text"   required ngModel name="firstName" #firstName="ngModel" id="firstName">
      <div  *ngIf="firstName.touched && !firstName.valid">
          <div *ngIf="firstName.errors && firstName.errors['required']">Email is required.</div>
      </div> -->
        <input type="text"  required [(ngModel)]="course.email" name="email" #email="ngModel" validateEmail>
        <div *ngIf="email.errors && (email.dirty || email.touched)" >
            <p [hidden]="!email.errors['required']">*required</p>
            <p [hidden]="!email.errors['emailInvalid']">{{email.errors['emailInvalid']}}</p>
        </div>
    </div>
    <button type="submit"  [disabled]="!courseForm.form.valid">Submit</button>
    <button type="reset"  (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>

template-driven-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;
  }

}

template-driven-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();
  });
});

CodePudding user response:

I suspect you have figured it out by now, but in your .spec file you want to add FormsModule to your imports:

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

...

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

CodePudding user response:

You have to import reactive forms module configuring in your template-driven-form.component.spec in configureTestingModule

You need to import everything you need in each test, so it doesn't matter that reactiveformsmodule is also imported in app.component.spec

  • Related