Angular - 动态添加 formControls 仅加载部分数据

Angular - adding dynamically formControls only loads partial data

提问人:AoiTora 提问时间:9/4/2023 更新时间:9/5/2023 访问量:36

问:

我正在开发一个 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(我的表单.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 指示在调用时,控件 inputABC123(以及与书籍数量一样多的输入)确实存在。它显示在错误之前。考虑到页面在脚本有时间将它们设置为控件之前尝试加载数据,我添加了 ,以便除非控件已经存在,否则它不会加载它们,但即使如此,错误仍然存在。此外,与页面中的元素进行交互(单击选择、展开面板等),将向列表中加载更多书籍,而无需重新加载页面。[这意味着,如果我与页面中的足够多的元素进行交互,我最终会得到一个功能表单 - 并不是说我可以要求用户单击按钮 25 次才能看到工作页面]ngIf="myBookFG.contains('input'+book.isbn)"

我怀疑这是一个与异步数据有关的问题,但我似乎无法确定如何解决这个问题。从输入中删除允许正确加载所有数据,但如果没有这个数据,我将无法从每个输入中获取选定的金额来计算要订购的书籍的总和。(我需要将此总和与表格上的不同输入进行比较以进行验证,并获取每本书输入的金额)formControlName='input{{book.isbn}}

异步 角度动力学形式

评论

0赞 MikeOne 9/4/2023
我猜这就是formArray的用途?
0赞 AoiTora 9/5/2023
我会查一下,看看这是否能解决问题

答:

0赞 AoiTora 9/5/2023 #1

这是该解决方案的更新。

原来缺少的只是一个 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>

如果没有该标记,解释器就无法知道它位于我定义的组中,也无法找到该组的内部控件。