【发布时间】:2018-08-25 11:46:29
【问题描述】:
我正在关注来自 Angular Material 网站的 this tutorial 关于创建自定义表单控件的信息。教程中没有关于在出现验证错误时如何处理表单控件错误的示例。
custom-text.component.html
<mat-form-field class="example-full-width">
<mat-select [placeholder]="placeholder" #select [formControl]="control">
<mat-option *ngFor="let food of foods" [value]="food">
{{food}}
</mat-option>
</mat-select>
<mat-error>This is required.</mat-error>
</mat-form-field>
custom-text.component.ts
import { Component, ViewChild, HostBinding, Input, ChangeDetectionStrategy, Optional, Self, DoCheck, OnInit, NgZone } from '@angular/core';
import { ControlValueAccessor, NgControl, NgForm, FormGroupDirective, FormControlDirective, FormControlName, FormControl, FormBuilder } from '@angular/forms';
import { MatFormFieldControl, MatSelect, CanUpdateErrorState, ErrorStateMatcher } from '@angular/material';
@Component({
selector: 'custom-text',
templateUrl: './custom-text.component.html',
styleUrls: [
'./custom-text.component.scss'
],
providers: [
{
provide: MatFormFieldControl,
useExisting: CustomTextComponent
}
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class CustomTextComponent implements ControlValueAccessor, OnInit, DoCheck {
@Input()
foods: string[];
@Input()
get errorStateMatcher(): ErrorStateMatcher {
return this.select.errorStateMatcher;
}
set errorStateMatcher(val) {
this.select.errorStateMatcher = val;
}
@Input()
get placeholder() {
return this.select.placeholder;
}
set placeholder(plh) {
this.select.placeholder = plh;
this.stateChanges.next();
}
@Input()
get value() {
return this.select.value;
}
set value(val) {
this.select.value = val;
this.stateChanges.next();
}
@ViewChild('select')
select: MatSelect;
control: FormControl;
constructor(
@Optional() @Self() ngControl: NgControl,
@Optional() private _controlName: FormControlName) {
if (ngControl) {
ngControl.valueAccessor = this;
}
}
ngOnInit(): void {
this.control = this._controlName.control;
}
ngDoCheck(): void {
this.select.updateErrorState();
}
writeValue(obj: any): void {
this.value = obj;
}
registerOnChange(fn: any): void {
this.select.registerOnChange(fn);
}
registerOnTouched(fn: any): void {
this.select.registerOnTouched(fn);
}
setDisabledState?(isDisabled: boolean): void {
this.select.setDisabledState(isDisabled);
}
}
app.component.html
<div style="text-align:center">
<form class="example-form" [formGroup]="myForm" (submit)="submitForm()">
<custom-text [foods]="[null, 'burger', 'spaghetti', 'fries']"
formControlName="selectedFood"
[errorStateMatcher]="matcher"></custom-text>
<button>Submit</button>
</form>
</div>
基本上,我将FormControlName 实例注入到自定义控件中。
constructor(
@Optional() private _controlName: FormControlName) {
....
ngOnInit(): void {
this.control = this._controlName.control;
}
然后我将它的control 属性绑定到内部mat-select 控件中。
<mat-select [placeholder]="placeholder" #select [formControl]="control">
然后我在ngDoCheck 中调用this.select.updateErrorState。
这是 StackBlitz 的链接: https://stackblitz.com/edit/angular-c4ufpp
有没有更好或更标准的方法?
【问题讨论】: