【问题标题】:Am I using FormArray correctly?我正确使用 FormArray 吗?
【发布时间】:2018-02-15 17:09:18
【问题描述】:

所以我有编译没有错误的代码,但是在使用时我得到一个错误...

我的表单组件:

export class OrderHeaderComponent implements OnInit {
    orderForm: FormGroup;
    orderLines: FormArray;

    ngOnInit() {
        // build the form model
        this.orderLines = this.fb.array([])
        this.orderForm = this.fb.group({

            orderHeadForm: this.fb.group({ // create nested formgroup to pass to child
                selectTypeahead: ['', 
                                    Validators.required],
                ohReference: ['', 
                                    Validators.required],
                }),

            orderLines: this.orderLines,

        })

    }

    someFunction(){
        this.orderLines.push(this.fb.group({
                    ['newInputName']: ['', 
                                    Validators.required],
                    }));
    }
}

现在这是一个父组件,它将表单传递给各个子组件(这可以减去我目前正在处理的 formArray 部分)。每个孩子看起来像这样: 父模板:

<form [formGroup]="orderForm" (ngSubmit)="orderFormSubmit()">
    <childTemplate [orderHeadForm]="orderForm.controls.orderHeadForm">
    </childTemplatet>
</form>

子模板:

<div class="form-group" [formGroup]="orderHeadForm">
        <label for="oh-custaccount">Customer Account #</label>

    <input class="form-control" type="text" 
    formControlName="selectTypeahead"
    (focusout)=lookupCustomerAccountReactive() />

    <p *ngIf="orderHeadForm.controls.selectTypeahead.errors?.required" 
    style="color:red;">Number required!</p>
</div>

子组件:

export class CustomerSelect implements OnInit {

    @Input() orderHeadForm: FormGroup;

....
}

现在,我什至没有尝试从 formArray 呈现新的表单输入,我只是想让它们创建时没有错误,这样我就可以在之后构建模板。但是目前,只要我调用 someFunction() 将新项目添加到 orderLines 数组,我的应用程序就会崩溃:

ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '{
"orderHeadForm": {
    "selectTypeahead": "",
    "ohReference": ""
},
"orderLines": []
}'. Current value: '{
"orderHeadForm": {
    "selectTypeahead": "",
    "ohReference": ""
},
"orderLines": [
    {
    "newInputName": ""
    }
]
}'

现在我看到了这个帖子:

how to access the index value of formarray of angular, when nested formControls are placed in a separate component?

但是如果我说 30 个子组件都需要这个,那么我的表单设置/构造可能有问题。我做错了什么/错误地使用了表单数组吗?由于文档中没有提到修复,我怀疑我的用例是独一无二的。

【问题讨论】:

  • @AJT_82 这是“我使用正确吗?”这让我很震惊,而且错误在于 JSON。收回。在做出决定之前,我需要更彻底地阅读这些内容。咖啡...
  • aah,删除了我的答案,因为我发现了它引发错误的原因。您的代码中存在错误,您是否检查过它们是否在您的实际代码中,例如['newInputName] 缺少'。我不明白为什么你会得到那个错误。但是尝试手动触发更改检测,就像您链接到的答案一样。在orderLines 中添加新的表单组后执行此操作。如果您可以尝试在 plunker 中重新创建问题,那将是最好的 :)
  • @R.Richards 哈哈,别担心,发生在我们最好的人身上,至少对我来说很多次:P
  • @AJT_82 在我的示例中是一个错字,我将在添加新行后尝试触发更改检测
  • 感谢@AJT_82 在创建表单元素后添加 ref.detectChanges() 工作,我想我必须为每个带有 Input 元素的孩子单独做一个 ngOnChanges(){},如果你想发布作为答案,我可以接受。

标签: angular


【解决方案1】:

由于某种原因,当您运行函数 someFunction 时,更改检测出现问题。您想知道是否需要根据您共享的链接在每个孩子中添加手动更改检测。但在这种情况下,这不是必需的。为什么?

原因是,设置@Input 时不会引发错误。这工作正常,不会抛出错误。当您在 parent 中调用函数 someFunction 时会发生错误,这向我们表明更改检测的问题就在此时。

通过在行后触发手动变化检测:

this.orderLines.push(this.fb.group({
   ['newInputName']: ['', Validators.required],
}));

因此应该足够了,不需要在每个孩子中触发变化检测。所以你的代码应该是这样的:

import {ChangeDetectorRef} from '@angular/core'

constructor(private ref: ChangeDetectorRef) { }

someFunction(){
  this.orderLines.push(this.fb.group({
     ['newInputName']: ['', Validators.required],
  }));
  this.ref.detectChanges();
}

【讨论】:

    猜你喜欢
    • 2014-02-28
    • 2015-06-25
    • 2022-01-08
    • 2011-08-07
    • 2011-09-26
    • 2019-05-03
    • 2016-03-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多