angular - Angular9 可重复使用的多自动完成芯片输入为 FormArray / ERROR TypeError: control.registerOnChange is not a function
问题描述
健康)状况
表格组件- 带有行创建/编辑按钮的表格。单击这些按钮中的任何一个时,将打开带有输入字段的相同对话框组件。输入字段是一个可重复使用的多自动完成芯片组件。如果用户单击“编辑行”,则必须将给定值设置为输入字段作为 mat-chips 并保持可编辑(删除芯片或添加新的)。如果选择“创建行” - 空输入,用户可以添加新的。
问题
当我打开编辑对话框时,我确实将表中的值设置为输入字段。但有了它我得到一个错误:
错误类型错误:control.registerOnChange 不是函数
我无法理解的对话框组件和输入组件之间存在联系。我认为问题出在FormControl和ControlValueAccessor中。
代码
对话框.component.ts:
this.fb.group({
*here are some working FormControls*,
managers: this.fb.array(this.someInterface.managers)
对话框.component.html:
<managers-auto-chips-selector
formControlName="managers">
</managers-auto-chips-selector>
input.component.html:
<mat-form-field appearance="outline">
<mat-label>Manager</mat-label>
<mat-chip-list #chipList>
<mat-chip
*ngFor="let item of selectedList"
[selectable]="selectable"
[removable]="removable"
(removed)="remove(item)">
{{item.name}}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
<input matInput
placeholder="Manager"
#managerInput
[matAutocomplete]="autocomplete"
[formControl]="managerControl"
[matChipInputFor]="chipList"
[matChipInputSeparatorKeyCodes]="separatorKeysCodes"
[matChipInputAddOnBlur]="addOnBlur"
(matChipInputTokenEnd)="add($event)">
</mat-chip-list>
<mat-autocomplete #autocomplete="matAutocomplete" (optionSelected)="selected($event)">
<mat-option *ngFor="let item of filteredList | async" [value]="item">
{{ item.name }}
</mat-option>
</mat-autocomplete>
</mat-form-field>
input.component.ts(添加):
filteredList: Observable<Manager[]>;
list: Manager[] = []; <--- managers list filled from API
selectedList: Manager[] = [];
managerControl = new FormControl();
constructor( @Optional() @Self() public ngControl: NgControl) {
if (this.ngControl != null) {
this.ngControl.valueAccessor = this;
}
}
ngOnInit(): void {
this.filteredList = this.managerControl.valueChanges.pipe(
map((manager: string | null) => {
return manager ? this._filter(manager) :
this.list.slice();
})
);
this.getManagersList();
}
private _filter(value: any): any[] {
return this.list.filter(manager => {
if (typeof value === 'string') {
return manager.fio.toLowerCase().includes(value.toLowerCase());
} else {
return manager.fio.toLowerCase().includes(value.fio.toLowerCase());
}
});
}
add(event: MatChipInputEvent): void {
const input = event.input;
const value = event.value;
// Add our fruit
if ((value || '').trim()) {
const item = this.list.filter(manager => {
return manager.fio.toLowerCase().includes(value.toLowerCase());
});
if (item.length === 1) {
this.selectedList.push(item[0]);
}
}
// Reset the input value
if (input) {
input.value = '';
}
this.managerControl.setValue(null);
}
selected(event: MatAutocompleteSelectedEvent): void {
this.selectedList.push(event.option.value);
this.managerInput.nativeElement.value = '';
this.managerControl.setValue(null);
}
registerOnChange(fn: any): void {
}
registerOnTouched(fn: any): void {
}
writeValue(item: any): void {
this.selectedList = item;
}
我有几个建议下一步该去哪里,但其中任何一个都会让我远离我目前的结果。仍然:
1) 在 dialog.component.htmlformControlName
到formArrayName
. 如果我这样做,则不会出现错误,但我的值没有设置并且我有空白输入。
2) 在 input.component.tsmanagerControl = new FormControl()
到new FormArray([ ])
. 然后我收到了一些(!)错误消息:
错误类型错误:control.registerOnChange 不是函数
3)要投入使用的东西registerOnChange
。无法得到它。
4) 以某种方式将每个 FormControl 从 dialog.components.ts 推managers: this.fb.array(this.someInterface.managers)
到 managerControl = new FormArray([]);
5) ???
任何意见或建议表示赞赏。
将根据需要提供任何更深入的解释、额外的代码或屏幕截图。
谢谢你。
解决方案
一些关于如何填充表单的代码会非常有用。
使用 FormArray 而不是 FormControl 作为managers
属性。如果你的价值观没有设定,那么你做错了。
您可以在下面找到一个示例,说明如何做到这一点并根据您的用例进行调整:
ngOnInit() {
this.myForm = this.fb.group({
...
managers: this.fb.array([], Validators.required),
});
this.myService.getWhatever().subscribe(whatever => {
if(whatever) {
this.myForm.setValue({
...
// set it to an empty array
managers: []
});
// push the data that you get to the form array
for (const manager of whatever.managers) {
this.managers.push(new FormControl(manager));
}
}
}
}
// Getter for retrieving the tags form array control from the parent form group
public get managers(): FormArray {
return this.myForm.get('managers') as FormArray;
}
<mat-chip-list #chipList formArrayName="managers">
<mat-chip
*ngFor="let manager of managers.controls; index as i"
>
{{ manager.name }}
<mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
</mat-chip>
</mat-chip-list>
推荐阅读
- java - 是否可以将多个 ORM 配置分配给 Java 模型?
- javascript - 自定义菜单项不可点击
- django - Django更新一对多数组
- ios - 如何确定在 UICollectionViewFlowLayout 中应该渲染多少个单元格?
- java - 获取 org.mockito.exceptions.misusing.PotentialStubbingProblem:严格的存根参数不匹配
- angular - Angular mat-autocomplete:以编程方式设置活动项目
- g1ant - 同时使用鼠标和键盘
- github - 从 CMake 读取 GitHub Pull Request 信息
- python - Python 生成器时间复杂度 log(n)
- r - 排队包 R -> M/M/c 队列:如何建模机器维修排队系统,但只允许 #servers 停机事件?