问题陈述
我正在尝试创建一个动态表单,其中部分界面响应模型的更新:
- 用户点击一个按钮
- 新的模型实体被添加到组件内部列表中,并创建了一个新的控件组(具有多个子控件,每个子控件都有专用的验证器)并将其附加到表单。
- 每个子控件都应该建立一个双向绑定,它在模型中的相应条目 [(ngModel)] 并将状态传播到顶层表单
我被困在哪里
我当前的问题是我不知道如何从模板中引用新的控制组(存储在 ControlArray 中)。
到目前为止,我发现的所有动态表单解决方案都没有支持模型和双向数据绑定。
代码
我为以下代码创建了一个 plunkr:https ://plnkr.co/edit/nP6hcIXKA0jz2F8Epg2L?p=preview
我的(简化的)数据模型:
class Entry {
constructor(
public _id: string,
public _title: string
) {}
}
class Data {
constructor(
public heading: string,
public entries: Entry[] = []
) {}
}
我的模板:
@Component({
selector: 'my-app',
template: `
<h1>Dynamic Form</h1>
<form [ngFormModel]="formModel">
<label>heading: </label>
<input type="text" [(ngModel)]="heading" [ngFormControl]="formModel.controls.heading">
<div>
<hr>
<!-- PROBLEM: how to get a reference to a single Control from within ControlGroup from within formModel.controls['entries'] that can be wired with belows <input> fields? -->
<div *ngFor="#entry of data.entries; #i = index">
<label>id: </label>
<input type="text" [(ngModel)]="entry._id" #ctrlId="ngForm"> <span><b>is valid: </b>{{ctrlId.control.valid}}</span>
<br>
<label>title: </label>
<input type="text" [(ngModel)]="entry._title" #ctrlTitle="ngForm"><span><b>is valid: </b>{{ctrlTitle.control.valid}}</span>
<hr>
</div>
</div>
</form>
<input type="button" (click)="add()" value="add new entry">
<div>{{ctrlCount}}</div>
<div>{{debug}}</div>
<div>{{debugForm}}</div>
`
})
我的组件:
export class DynamicForm implements OnInit {
data:Data;
formModel:ControlGroup;
constructor(private fb:FormBuilder) {
this.formModel = fb.group({
heading: fb.control('test heading', Validators.required),
entries: fb.array([])
})
}
ngOnInit():void {
/* init the heading */
this.data = new Data('test heading');
/* init the entries > add to model, create control and add it to ControlArray */
[
new Entry('1', 'one'),
new Entry('2', 'two'),
new Entry('3', 'three'),
new Entry('4', 'four'),
].forEach((e:Entry) => this.add(e));
}
add(e:Entry):void {
let id:string = e ? e._id : '';
let title:string = e ? e._title : '';
(<ControlArray>this.formModel.controls['entries']).push(this.fb.group({
id: this.fb.control(id, Validators.required),
title: this.fb.control(title, Validators.required),
}));
this.data.entries.push(new Entry(id, title));
}
get debug() {
return JSON.stringify({debug_data: this.data});
}
get debugForm() {
return JSON.stringify({
debug_form: {
dirty: this.formModel.dirty,
pristine: this.formModel.pristine,
touched: this.formModel.touched,
untouched: this.formModel.untouched,
valid: this.formModel.valid,
}
});
}
get ctrlCount() {
return (<ControlArray>this.formModel.controls['entries']).length;
}
}