我正在开发一个 Angular 表单,它从服务获取一些数据,以便用输入填充表单。假设这是一种订购书籍的表单。 用户之前选择了一种类型,并且该服务返回了适合该类型的书籍列表。因为根据类型的不同,我们不会总是获得相同数量的书籍,所以我必须找到一个周转方案,以便生成具有不同 formControlName 的输入。这是我的表格的样子(简化版本,希望我没有犯任何错字):
myForm.html
<form name="form" [formGroup]="mainForm">
<ng-template ngFor let-book [ngForOf]='datas.books'>
<div>
<span> {{book.title}}</span>
</div>
<div *ngIf="myBookFG.contains('input'+book.isbn)">
<mat-form-field>
<mat-label>Amount to order</mat-label>
<input matInput maxlength='16'formControlName='input{{book.isbn}}' >
</mat-form-field>
</div>
</ng-template>
</form>
myForm.ts
mainForm!: FormGroup;
myBookFG!: FormGroup;
whenSelectedGenreIsChanged(): void {
//[...]
this.bookService.getBooksFromGenre(this.selectedGenre)
.subscribe( (next) => {
if (next){
this.datas = next;
this.changeBookList();
}
});
}
changeBookList(): void{
// Resetting the previous formGroup
this.mainForm.removeControl('myBookFG');
// Then creating a new one populated with the books of the selected genre
this.myBookFG= this.formBuilder.group([]);
for (const book of datas.books){
const inputName = "input" + book.isbn;
this.myBookFG.addControl(inputName, this.formBuilder.control( '', []));
}
this.mainForm.addControl('myBookFG', this.myBookFG);
console.log("Books added : ", this.myBookFG); //Checking if all books controls are imported
}
现在的问题是:这编译得很好,但是,在加载页面时,我最多只能得到列表上显示的几个输入,并且来自浏览器控制台的此错误:
ERROR Error: Cannot find control with name: 'inputABC123'
at _throwError (forms.mjs:1778:11)
at setUpControl (forms.mjs:1567:13)
at FormGroupDirective.addControl (forms.mjs:5337:9)
at FormControlName._setUpControl (forms.mjs:5893:43)
at FormControlName.ngOnChanges (forms.mjs:5838:18)
at FormControlName.rememberChangeHistoryAndInvokeOnChangesHook (core.mjs:1515:14)
at callHook (core.mjs:2568:18)
at callHooks (core.mjs:2527:17)
at executeInitAndCheckHooks (core.mjs:2478:9)
at refreshView (core.mjs:9525:21)
console.log 表明调用时,控制输入ABC123(以及与书籍一样多的输入)确实存在。它显示在错误之前。认为页面试图在脚本有时间将数据设置为控件之前加载数据,我添加了 ngIf="myBookFG.contains('input'+book.isbn)"
,这样除非控件已经存在,否则它不会加载它们,但即使如此,错误仍然存在存在。此外,与页面中的元素交互(单击选择、展开面板等)将在列表中加载更多书籍,而无需重新加载页面。 [这意味着,如果我与页面中足够多的元素进行交互,我最终会得到一个功能表单 - 而不是我可以要求用户单击按钮 25 次才能查看工作页面]
formControlName='input{{book.isbn}}
可以让所有数据正确加载,但如果没有这个,我将无法从每个输入中获取选定的金额来计算要订购的书籍的总和。 (我需要将此金额与表单上的不同输入进行比较以进行验证,以及获取每本书输入的金额)
事实证明,缺少的只是一个 formGroupName。
<form name="form" [formGroup]="mainForm">
<ng-template ngFor let-book [ngForOf]='datas.books'>
<div formGroupName="myBookFG">
<span> {{book.title}}</span>
</div>
<div *ngIf="myBookFG.contains('input'+book.isbn)">
<mat-form-field>
<mat-label>Amount to order</mat-label>
<input matInput maxlength='16'formControlName='input{{book.isbn}}' >
</mat-form-field>
</div>
</ng-template>
</form>
如果没有这个标签,解释器就无法知道它在我定义的组内,也无法找到该组的内部控件。