如何在角度5中动态地将FormControl添加到FormGroup?

时间:2018-02-16 19:43:00

标签: angular angular-forms

我正在尝试构建一个与FormGroup兼容的数据表。 FormArray。我将使用parentForm组将标题详细信息和行传递给此组件。

我创建了一个小的添加按钮,点击它后,我会动态添加新项目。在这种情况下,UI正在更新,但如果我打印formGroup.value(),我只获得传递的初始值。不是更新的formControl。我不确定我错过了什么。

export class FormTableComponent implements OnChanges {
    @Input() headers: Array<string>;
    @Input() rows: Array<any>;
    @Input() parentFG: FormGroup;
    @Input() entriesName: string;

    get entries(): FormArray {
        return <FormArray>this.parentFG.get(this.entriesName);
    }

    constructor(private fb: FormBuilder, private cd: ChangeDetectorRef) {}

    ngOnChanges() {
        this.createFormControls();
    }

    createFormControls() {
        this.parentFG.controls[this.entriesName] = this.fb.array([]);
        this.rows.forEach(row => {
            this.entries.controls.push(this.fb.group(row));
        });
    }
}

DEMO

2 个答案:

答案 0 :(得分:3)

你有几个问题: 1.将新行推送到FormArray以外的FormArray控件

AnalysisException: 'No such struct field age in name, value; line 16 pos 8'

应该是

this.entries.controls.push(this.fb.group(row));

2。不是每次都创建新的FormArray并在调用this.entries.push(this.fb.group(row)); 时重新加载每一行,您可以通过createFormControls()方法访问它

解决方案1:

检查get entries()的长度,如果为0,则使用entries进行初始化,否则只需将最后一行推入现有的rows

FormArray

解决方案2:

就个人而言,我更喜欢将createFormControls() { const keys = Object.keys(this.entries.value); if( keys.length === 0) { this.rows.forEach(row => { this.entries.push(this.fb.group(row)); }); } else { const row = this.rows[this.rows.length - 1]; this.entries.push(this.fb.group(row)); } } createFormArray()appendTo()放入父组件中。它干净,易读。在这种情况下,我们不需要popFrom()

我已将ChangeDetectionRefcreateFormControls()组件移至form-table组件,并将其重命名为dummy并稍稍更改createFormArray(),现在一切正常< / p>

addNewRow()

初始化虚拟表单时,请执行以下操作:

// create FormArray once
createFormArray() {
    const elements: any[] =[];

    this.rows.forEach(row => {
        elements.push(this.fb.group(row));
    });
    return this.fb.array(elements);
}

addNewRow() {
  const newRow =    {
            name: 'NAFFD',
            age: 12,
            place: 'TN'
        };

    this.rows.push(newRow);  // update rows

    const persons =  this.dummyForm.get('persons') as FormArray;
    persons.push(this.fb.group(newRow));  // update FormArray
}

enter image description here

希望它有帮助并且编码愉快!

答案 1 :(得分:0)

这是对ngOnChanges的常见误解。 ngOnChanges最适合Primitive Types,因为它们是按值传递的。

Javascript中的对象和数组通过引用传递。话虽如此,ngOnChanges正在寻找提供改变的输入值。在这种情况下,对Array的引用是提供的输入,而不是Array中的值。因此,除非您将新数组传递给组件,否则ngOnChanges将不会触发,因此不会重新呈现您的表单。

一个快速而又脏的解决方案可能是每次在Parent端更新它时重新实例化Object / Array。

this.rows = Object.assign([], newRows);

这将创建一个全新的数组,该数组应该反过来更改引用,最后强制ngOnChanges触发孩子。

或者,您可以某种方式将您的行转换为Observable并在子项内订阅它。就个人而言,Observables是一种更清晰的方式来处理原始类型之外的变化检测。 Here是关于通过服务进行父/子通信的文档的一篇很好的文章。