【问题标题】:No value accessor for form control with name... for mat-select controls具有名称的表单控件没有值访问器...用于垫选择控件
【发布时间】:2019-04-16 23:56:42
【问题描述】:

我正在使用 jasminekarmaangular 6 应用程序进行一些单元测试,以验证 formGroup 字段有效。我在使用 mat-select 控制时遇到问题。当我运行测试用例时,Karma 给我一个错误提示 Error: No value accessor for form control with name: 'importId'。顺便说一句,该组件按我的预期运行良好。

这是我的组件:

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),
    });
  }
}

我的 HTML 模板如下所示:

<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>

最后,这是我的单元测试:

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

  });
});

我无法做到这一点,有什么我缺少的建议吗?

【问题讨论】:

  • 您没有在测试模块中导入材料模块。所以 mat-form-field、mat-select 等只是被 Angular 视为未知元素(因为您使用 NO_ERRORS_SCHEMA 告诉它这样做)。
  • @JBNizet,太棒了。这对我行得通。我真的很感激。随意在此提要中提供答案。
  • 我遇到了同样的问题,但使用了 mat-checkbox。我将 MatCheckboxModule 添加到 TestBed 导入中,它解决了错误,谢谢!
  • 对于那些使用mat-button-toggle-group 的人,您需要将MatButtonToggleModule 添加到您的TestBed 导入中,不需要NO_ERRORS_SCHEMABrowserAnimationsModule

标签: angular typescript unit-testing angular-material karma-jasmine


【解决方案1】:

您没有在测试模块中导入材料模块。

所以 mat-form-fieldmat-select 等只是被 Angular 视为未知元素(因为您使用 NO_ERRORS_SCHEMA 告诉它这样做)。

【讨论】:

  • 像魅力一样工作。另外,我包括了BrowserAnimationsModule
  • 拯救了我的一天。谢谢!!
  • 使用NO_ERRORS_SCHEMA 是个坏主意。它会掩盖您的测试的其他问题。请改用CUSTOM_ELEMENTS_SCHEMAmedium.com/@fivedicephoto/… 解释了更多原因。
【解决方案2】:

在我的情况下,我忘记了

import {MatSelectModule} from '@angular/material/select';

在模块中。

所以如果你导入它应该可以工作。

【讨论】:

    【解决方案3】:

    我认为您缺少一些重要的模块,这就是 Angular 编译器不知道这些的原因。在您的导入中至少添加以下内容(我猜还有更多):

    imports: [ReactiveFormsModule, FormsModule,
      BrowserModule,
      BrowserAnimationsModule,
      MatSelectModule,
      MatOptionModule,
      MatInputModule
    ],
    

    也可以使用

    schemas: [CUSTOM_ELEMENTS_SCHEMA],
    

    告诉编译器能够检测非 HTML 标签。

    通过该修复,您将不再需要 NO_ERRORS_SCHEMA,在这些简单的情况下不应使用它。

    【讨论】:

      猜你喜欢
      • 2020-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-07
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多