No value accessor for form control with name... for mat-select controls
Solution 1
You're not importing the material modules in your testing module.
So mat-form-field
, mat-select
, etc. are just treated as unknown elements by Angular (since you told it to do so by using NO_ERRORS_SCHEMA
).
Solution 2
In my case I forgot
import {MatSelectModule} from '@angular/material/select';
in module.
So if you import it should work.
Solution 3
I think you're missing some important modules, that's why those are not known to the Angular compiler. Put at least the following (and more I guess) in your imports:
imports: [ReactiveFormsModule, FormsModule,
BrowserModule,
BrowserAnimationsModule,
MatSelectModule,
MatOptionModule,
MatInputModule
],
Use also
schemas: [CUSTOM_ELEMENTS_SCHEMA],
to tell the compiler to be able to detect non-HTML tags.
With that fix, you won't need the NO_ERRORS_SCHEMA
, which should NOT be used in these simple cases.
xzegga
Updated on June 29, 2022Comments
-
xzegga almost 2 years
I am making some unit test with jasmine and karma for an angular 6 app that validate if a formGroup field is valid. I am experiencing problems with mat-select control. when I run the test case, Karma fires me an error saying
Error: No value accessor for form control with name: 'importId'
. By the way, the component works fine as I expected.This is my component:
import {Component, Inject, OnInit} from '@angular/core'; import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material"; import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms"; @Component({ selector: 'app-my-component', templateUrl: './my.component.html', styleUrls: ['./my.component.css'] }) export class MyComponent implements OnInit { modelForm: FormGroup; imps; constructor( public dialogRef: MatDialogRef<MyComponent>, @Inject(MAT_DIALOG_DATA) public data: any) { this.imps = data['imp']; } ngOnInit() { this.modelForm = new FormGroup({ name: new FormControl(null, Validators.required), importId: new FormControl(null, Validators.required), }); } }
My HTML template looks like this:
<mat-dialog-content> <form [formGroup]="modelForm"> <mat-form-field> <input matInput placeholder="Name" formControlName="name"> </mat-form-field> <mat-form-field> <mat-select placeholder="Source import" formControlName="importId"> <mat-option *ngFor="let imp of imps" [value]="imp.uuid"> {{imp.label}} </mat-option> </mat-select> </mat-form-field> </form> </mat-dialog-content> <mat-dialog-actions> <button mat-raised-button color="primary" [disabled]="!modelForm.valid" (click)="someFakeFunction()">Create</button> <button mat-raised-button (click)="dialogRef.close()">Cancel</button> </mat-dialog-actions>
Finally, this is my unit test:
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {MockMatDialogData, MockMatDialogRef} from '@testing/mock/material'; import {MyComponent} from './evaluation-wizard.component'; import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material"; import {FormsModule, ReactiveFormsModule} from "@angular/forms"; import {NO_ERRORS_SCHEMA} from "@angular/core"; describe('MyComponent', () => { let component: MyComponent; let fixture: ComponentFixture<MyComponent>; beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [MyComponent], imports: [ReactiveFormsModule, FormsModule], providers: [ {provide: MatDialogRef, useValue: MockMatDialogRef}, {provide: MAT_DIALOG_DATA, useClass: MockMatDialogData} ], schemas: [NO_ERRORS_SCHEMA], }) .compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(MyComponent); component = fixture.componentInstance; component.ngOnInit(); fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); describe('Form validation', () => { it('form invalid when empty ', function () { expect(component.modelForm.valid).toBeFalsy(); }); it('name field validity ', () => { let name = component.modelForm.controls['name']; expect(name.valid).toBeFalsy(); let errors = {}; errors = name.errors || {}; expect(errors['required']).toBeTruthy(); name.setValue("test"); errors = name.errors || {}; expect(errors['required']).toBeTruthy(); }); }); });
I can't make that works, any suggestions what I am missing?