表单控件不适用于 Angular Material Mat-select

Posted

技术标签:

【中文标题】表单控件不适用于 Angular Material Mat-select【英文标题】:Form Control not working for Angular Material Mat-select 【发布时间】:2020-03-09 12:59:41 【问题描述】:

我有一个 mat-select 表单元素绑定到 FormControl 以进行验证。目标是如果未填写选择框(或未选择任何内容),则在元素下方给出一个错误框

但是,当提交时没有选择选择选项,即使我有一个必需的选项,表单也是有效的。

<form [formGroup]="cityForm" (submit)="submit()">

<mat-form-field>
   <mat-label>Select City</mat-label>

   <mat-select [(ngModel)]="city.Id"
               [formControl]="cityFormControl"
               [errorStateMatcher]="matcher">
                <mat-option *ngFor="let c of dropdowns.Cities"
                            [value]="c.Id">
                    c.Name
                </mat-option>
   </mat-select>

   <mat-error *ngIf="cityFormControl.hasError('required')">
     City is <strong>required</strong>
   </mat-error>

控制器代码:

//Angular Imports
import  Component, Input, OnInit  from '@angular/core';
import  FormControl, FormGroup, FormGroupDirective, NgForm, Validators  from '@angular/forms';
import  ErrorStateMatcher  from '@angular/material/core';

@Component(
    ...
)
export class CityComponent implements OnInit 

    city: any = ;
    dropdowns: any = ;

    //      Form Control Variables
    matcher = new MyErrorStateMatcher();

    cityFormControl = new FormControl('', [Validators.required]);

    cityForm = new FormGroup(
        city: this.cityFormControl
    );


    constructor() 
    

    ngOnInit(): void 

       this.dropdowns = [
                         Id: 1, Name: "Toronto", 
                         Id: 2, Name: "Chicago"
                        ];
    

    submit(form : FormGroup): void 

        if (form.valid == false) 
            //doesn't get called
            return;
        

        return;  


/** Error when invalid control is dirty, touched, or submitted. */
export class MyErrorStateMatcher implements ErrorStateMatcher 
    isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean 
        const isSubmitted = form && form.submitted;
        return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
    

知道为什么所需的验证不起作用吗?

【问题讨论】:

可能是因为您正在混合 ngModel 和表单控件,请选择一个 我从未见过以这种方式设置的表单组是您不立即创建它的原因吗? cityForm = new FormGroup( city:new FormControl('', [Validators.required]) ); @bryan60 如果没有 ngModel,你如何绑定一个值? 在表单控件上使用 setValue。如果你告诉我如何/何时定义城市,我可以告诉你如何。 【参考方案1】:

您需要提供控件名称,然后通过在您定义的控件上调用valid让材质表单处理错误。

<form [formGroup]="cityForm" (submit)="submit()">

<mat-form-field>
   <mat-label>Select City</mat-label>

   <mat-select formControlName="cityFormControl"  // Form group is set by form tag
               [compareWith]="CompareCity">       // You need to define a compare method
                <mat-option *ngFor="let c of dropdowns.Cities"
                            [value]="c.Id">
                    c.Name
                </mat-option>
   </mat-select>

   <mat-error *ngIf="!cityForm.controls['cityFormControl'].valid && cityForm.controls['cityFormControl'].touched">
     City is <strong>required</strong>
   </mat-error>

比较函数看起来像这样:

  public CompareCity(Param1: City, Param2: City) : boolean 
    return Param1 && Param2 ? Param1.Id === Param2.Id : false;
  

【讨论】:

这里不需要比较方法。 select的值为ID,只要将表单控件值设置为你想要的ID即可。 我认为这是一个很好的答案【参考方案2】:

参考What are the practical differences between template-driven and reactive forms?

请看下面的例子:

constructor(private fb: FormBuilder)  

cityForm: FormGroup;

ngOnInit(): void 
  this.cityForm = this.fb.group(
    city: ['', [Validators.required]]
  )

get city()  return this.cityForm.get("city") 
<form [formGroup]="cityForm" (submit)="submit()">
  <mat-select [formControl]="city" [errorStateMatcher]="matcher">
    <mat-option *ngFor="let c of dropdowns.Cities" [value]="c.Id">
      c.Name
    </mat-option>
  </mat-select>

  <mat-error *ngIf="city.hasError('required')">
    City is <strong>required</strong>
  </mat-error>
</form>

【讨论】:

以上是关于表单控件不适用于 Angular Material Mat-select的主要内容,如果未能解决你的问题,请参考以下文章

Angular Material Tabs 不适用于包装器组件

必需属性不适用于Angular Js中的文件输入

异步验证器不适用于 Angular 中的模板驱动表单

Angular 4 表单验证器 - minLength 和 maxLength 不适用于字段类型号

Angular 6 Material mat-select 更改方法已删除

验证失败时阻止表单提交(Angular Material)