我在stackblitz中留下了基于材料输入的最简单的自定义表单控件。
如您所见,它实现了 ControlValueAccessor,它具有以下功能:
onChange:any; //declare this function to indicate in any time that you change the value
onTouched:any; //declare this function to indicate in any time that your compoment is touched
writeValue(value: any[]|any): void {
this.value=value;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState(isDisabled: boolean): void {
this.disabled=isDisabled
}
和像这样的提供者
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomMat),
multi: true
}
如果要在组件内部进行验证,则需要添加一个新的提供者
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => CustomMat),
multi: true,
}
并创建函数 validate
validate(control: AbstractControl): ValidationErrors | null{
//your logic here
return null;
}
我又使用了这两个功能:
setValue(value: any){
this.value=value;
this.onChange(value);
}
focusOut()
{
this.onTouched()
}
调用更改和触摸的功能
01.04.20更新好了,这个自定义素材输入的问题是错误在输入中看不到反映,所以我们要做一些修改
这个想法是添加一个 customError 匹配器
export class CustomFieldErrorMatcher implements ErrorStateMatcher {
constructor(private customControl: AbstractControl,private errors:any) { }
isErrorState(control: AbstractControl | null, form: FormGroupDirective | NgForm | null): boolean {
return this.customControl && this.customControl.touched && this.customControl.invalid;
}
}
如果控件无效,那就是我们的内部输入无效。那么,很难知道这个“控制”是什么。为此,我们在 ngAfterViewInit 中注入了 NgControl,这个 ngControl 将成为我们的控件,噗
ngAfterViewInit(): void {
const ngControl: NgControl = this.injector.get(NgControl, null);
if (ngControl) {
setTimeout(() => {
this.control = ngControl.control;
this.matcher = new CustomFieldErrorMatcher(this.control,null);
})
}
}
至少添加这个匹配器
<input name="input" matInput [ngModel]="value"
(ngModelChange)="setValue($event)"
[errorStateMatcher]="matcher" >
你可以在这个 stackblitz中看到