angular - Angular 自定义 ControlValueAccessor 无法处理数组
问题描述
我有一个自定义的 ControlValueAccessor 来处理数组的值。
import { Component, forwardRef, Input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'app-custom-control',
templateUrl: './custom-control.component.html',
styleUrls: ['./custom-control.component.scss'],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CustomControlComponent),
multi: true,
}]
})
export class CustomControlComponent implements ControlValueAccessor {
disabled: boolean;
@Input()
value: string[] = [];
constructor(
) { }
addElement(text: string) {
this.value.push(text);
this.value = [].concat(this.value);
this.emitValueChange();
}
removeElement(text: string) {
this.value.splice(this.value.indexOf(text), 1);
this.value = [].concat(this.value);
this.emitValueChange();
}
emitValueChange(): void {
this.onChange(this.value);
}
writeValue(obj: string[]): void {
this.value = obj;
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onChange = fn;
}
onChange = (obj: any) => {
};
onTouched = () => {
};
}
然后我有一个自定义验证器来检查是否至少存在一个元素。
export class CustomValidators {
static minSelected(min: number = 1): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if (control.value == null || !Array.isArray(control.value)) {
// value is null or not an array
return { minSelected: min, actualSelected: 0 };
}
else if (control.value.length < min) {
// not enough
return { minSelected: min, actualSelected: control.value.length };
}
else {
// good to go
return null;
}
}
}
}
我在 FormGroup 中像这样使用它。
this.formGroup = this.formBuilder.group({
events: new FormControl([], [CustomValidators.minSelected(1)]),
});
问题是,Angulars Forms 在初始化后没有检测到值的变化。我使用模板上的按钮和输入调用#addElement 和#removeElement 函数。当我对数组执行 console.log 时,我可以看到所有的变化。DOM 也会相应地更新。但是由于某种原因,当我更改数组的值时,不再调用验证器。因此不再拾取非法状态(如无元素/空数组),我无法正确验证表单。
解决方案
我是一个白痴。
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onChange = fn;
}
敏锐的眼睛可能会注意到,我还将“触摸”处理程序绑定到更改处理程序。我假设 Angular 因此覆盖了“更改”处理程序,因为它在“触摸”处理程序之前被绑定。
愚蠢的错误,花了我几个小时。爱它。
推荐阅读
- tensorflow - 为什么批量标准化会降低我的模型训练准确性?
- css - 浮动内容
- firebase - Firebase 安装并首次在 iOS 上运行后不显示通知
- visual-studio-code - 在 Vscode 的区块链平台扩展中将客户端应用程序连接到在本地结构网络上运行的 Nodejs 链代码
- vue.js - Vuestorefront without SSR - asyncData not triggered
- javascript - 带有 Google Sheet API 的 Live Json 数据搜索 Ajax jQuery
- c++ - 为什么我会收到“运行时错误:AddressSanitizer:致命信号”?
- gerrit - 如何通过 REST API 获取 gerrit 中的历史消息
- r - renv::restore() 错误:无法检索“包”(使用私有包)
- c# - Enviroment.Exit 后启动进程