我正在尝试构建一个与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));
});
}
}
答案 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()
。
我已将ChangeDetectionRef
从createFormControls()
组件移至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
}
希望它有帮助并且编码愉快!
答案 1 :(得分:0)
这是对ngOnChanges
的常见误解。 ngOnChanges
最适合Primitive Types,因为它们是按值传递的。
Javascript中的对象和数组通过引用传递。话虽如此,ngOnChanges
正在寻找提供改变的输入值。在这种情况下,对Array的引用是提供的输入,而不是Array中的值。因此,除非您将新数组传递给组件,否则ngOnChanges
将不会触发,因此不会重新呈现您的表单。
一个快速而又脏的解决方案可能是每次在Parent端更新它时重新实例化Object / Array。
this.rows = Object.assign([], newRows);
这将创建一个全新的数组,该数组应该反过来更改引用,最后强制ngOnChanges
触发孩子。
或者,您可以某种方式将您的行转换为Observable
并在子项内订阅它。就个人而言,Observables是一种更清晰的方式来处理原始类型之外的变化检测。 Here是关于通过服务进行父/子通信的文档的一篇很好的文章。