📅  最后修改于: 2023-12-03 15:17:32.912000             🧑  作者: Mango
在使用 Angular Material 表单时,mat-form-field 是一个常见的组件,用于包装输入控件。但是,它不能直接包装常规的 HTML 输入控件。因此,需要使用 MatFormFieldControl 接口来定义自己的控件类型,并将其直接或间接地使用在 mat-form-field 组件内。以下是一个简单的示例:
import { Component } from '@angular/core';
import { FormControl, NgControl, NgForm } from '@angular/forms';
import { MatFormFieldControl } from '@angular/material/form-field';
import { Subject } from 'rxjs';
@Component({
selector: 'custom-input',
templateUrl: './custom-input.component.html',
styleUrls: ['./custom-input.component.css'],
providers: [{ provide: MatFormFieldControl, useExisting: CustomInputComponent }],
// 将自定义的输入控件注册为 MatFormFieldControl
})
export class CustomInputComponent implements MatFormFieldControl<string> {
static nextId = 0;
stateChanges = new Subject<void>();
focused = false;
errorState = false;
controlType = 'custom-input';
id = `custom-input-${CustomInputComponent.nextId++}`;
onChange = (_: any) => {};
onTouched = () => {};
value: string;
constructor(private ngControl: NgControl) {
if (this.ngControl != null) {
this.ngControl.valueAccessor = this;
}
}
get empty() {
return !this.value;
}
get shouldLabelFloat() {
return this.focused || !this.empty;
}
get placeholder() {
return 'Enter text';
}
get required() {
return false;
}
setDescribedByIds(ids: string[]): void {}
onContainerClick(event: MouseEvent): void {
this.focused = true;
this.onTouched();
}
writeValue(value: string): void {
this.value = value;
this.onChange(value);
this.stateChanges.next();
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
this.focused = false;
this.errorState = false;
}
ngOnDestroy() {
this.stateChanges.complete();
}
}
在上述示例中,CustomInputComponent 实现了 MatFormFieldControl 接口,并将自身注册为一个提供者,实现方式与 Angular Material 的默认实现类似。接口中定义了一些必须实现的属性和方法,包括状态变化的 Subject,是否焦点状态,是否有错误状态,控件类型,控件 ID,变更回调函数等等。需要注意的是,该接口是一个泛型接口,支持根据自己的数据模型定义相应的泛型参数。
在定义好自定义控件后,可以将其放入 mat-form-field 作为其子节点,或者将其放到间接子节点里,如下所示:
<mat-form-field>
<custom-input placeholder="Enter your text"></custom-input>
</mat-form-field>
这样就能够自定义输入控件,使其与 Angular Material 表单更好地配合使用了。
总之,使用 mat-form-field 进行表单构建时,必须确保其包含一个实现了 MatFormFieldControl 接口的控件,以便能够和输入框产生关联。