首页 文章

angular2动态形式与* ngFor,双向绑定[(ngModel)]和表单验证

提问于
浏览
3

问题陈述

我正在尝试创建一个动态表单,其中界面的某些部分响应模型的更新:

  • 用户点击按钮

  • 新模型实体被添加到组件内部列表中,并创建 new control group (具有多个子控件,每个具有专用验证器)并附加到表单 .

  • 这个子控件中的每一个应该 Build 一个双向绑定,它在模型[(ngModel)]中对应的条目并将状态传播到顶级表单

我被困在哪里

我目前的问题是我不知道如何从模板中引用 new control group (存储在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;
    }
}

1 回答

相关问题