表单控件不适用于 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 4 表单验证器 - minLength 和 maxLength 不适用于字段类型号