我已经在Angular 8中专门切换到了反应形式,并且虽然进步不错,但是在自定义控件方面却遇到了一个绊脚石。我了解基本知识,并且有一些示例可以正常工作。但是,在一种情况下,我有一个目标,我无法100%地实现期望。
目标:一个简单的复选框驱动的多重选择列表,其中添加了一个文本输入字段,该文本输入字段允许在选择列表中添加“其他”值。控件将输出一个逗号分隔的选定值列表。
困难因素:控件所在的表单需要提供实时验证反馈。也就是说,选择控件应包含验证文本,以告知用户“至少需要一项”,这意味着他们必须选择一个或多个值,并且可能在“其他”字段中包含一个条目。
除了用户在“其他”输入中输入第一个字符或清除“其他”输入中的所有字符而不会进行验证之外,我已经完全完成了所有工作仍然专注于该控件。
自定义控件的相关部分:
@Component({
selector: 'app-selection-list-form',
templateUrl: './selection-list-form.component.html'
,providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => SelectionListFormComponent),
multi: true
},
{
provide: NG_VALIDATORS,
useExisting: SelectionListFormComponent,
multi: true
}
]
})
export class SelectionListFormComponent implements OnInit, ControlValueAccessor {
public selectionList: string[] = new Array<string>();
...
get value(): string {
return this._value;
}
set value(change) {
this._value = change;
this.onChange;
this.onTouched;
}
onChange: any = () => { };
onTouched: any = () => { };
propagateChange = (_: any) => { };
public writeValue(change: any): void {
this.value = change;
}
registerOnChange(fn: (v: any) => void): void {
this.propagateChange = fn;
}
registerOnTouched(fn: () => void): void {
this.onTouched = fn;
}
observeOther = (text$: Observable<string>) => text$.pipe(
debounceTime(100), switchMap(term => {
this.toggleSelection("other", term);
return [];
})
);
toggleSelection(type?: string, term?: string): any {
...
this.propagateChange(this.selectionList.join(","));
}
}
我在“其他”输入字段上输入了这样的内容:
<input #otherElement
type="text"
[ngbTypeahead]="observeOther" />
我没有展示该toggleSelection
方法内部的所有逻辑,因为它不相关。它会查看所有内容,并根据需要操纵选择数组,并最终将控件的值设置为上述逗号分隔的字符串列表。
所有这些都有效,但是,当“其他”字段正在更新时,我的主要形式并没有“看到”底层自定义控件的更新验证状态。如果我将实时结果写入控制台日志,则可以清楚地看到,随着我的键入,控件的值似乎始终是最新的,并且控件的错误对象也是如此,但是主要表单似乎没有收到该消息。显然,我缺少一个步骤,在该步骤中我需要发出一些信息或更新某些内容以获取主要信息以获取及时的消息。
我想念什么?