如何使用反应形式将表格绑定到Angular 6中的模型?

时间:2018-07-14 19:37:22

标签: angular

在角度6之前,我使用[(ngModel)]将表单字段直接绑定到模型。现在不推荐使用(不能用于反应式表单),而且我不确定如何用表单值更新模型。我可以使用form.getRawValue(),但是这需要我用新的rawValue替换当前模型-这是不利的,因为我的主模型比本地表单模型更大并且具有更多的字段。

有什么想法吗?

3 个答案:

答案 0 :(得分:7)

Angular Documentation中更详尽地说明的那样,对于反应式表单,您不会将表单直接绑定到您的模型。而是,您使用FormBuilder构建一个FormGroup对象(本质上是“表单”),该对象将维护其自己的模型。 在构建过程中,您将有机会以表单的形式设置初始值,通常可以通过您的模型进行设置。

然后将模板中的表单控件绑定到表单的模型。 用户与表单控件的交互将更新表单的模型。

当您准备对表单数据进行某些操作(例如“提交”表单)时, 您可以使用FormGroup的value属性或getRawValue()方法从表单字段中获取值-这两种行为不同,请参阅文档以获取详细信息。

一旦您从表单中获取值,就可以使用表单中的值更新您的模型。

答案 1 :(得分:4)

如果要绑定到文本输入之类的表单控件,请像使用其他任何反应形式一样使用此语法:

<ng-container [formGroup]="this.myFormGroup">
    <input type="text" formControlName="field1">
    <input type="text" formControlName="field2">
    <ng-container formGroupName="subgroupName">
        <input type="text" formControlName="subfield2">
    </ng-container>
</ng-container>

在组件类的constructor()中(应在模板呈现之前),使用以下语法来构建一个表单组以与该表单进行对话:

import { FormBuilder, FormGroup, Validators } from '@angular/forms';

...
    constructor(private formBuilder: FormBuilder) {
        this.myFormGroup = this.formBuilder.group({
            field1: [],
            field2: [],
            subgroupName: this.formBuilder.group({
                subfield2: [],
            }),
        });
        this.retrieveData();
    }

如果您的组件需要在加载时从服务中检索数据,则必须确保它在构建表单后开始传输,然后使用patchValue()将对象中的数据放入{{ 1}}:

FormGroup

private retrieveData(): void { this.dataService.getData() .subscribe((res: SomeDataStructure) => { this.myFormGroup.patchValue(res); }); } 模型的只读数据绑定的访问有所不同:

FormGroup

所有这些技术消除了对任何{{ this.myFormGroup.get('field1').value }} {{ this.myFormGroup.get('subgroupName.subfield2').value }} 绑定的需求。

答案 2 :(得分:1)

您可以订阅表单组中的更改,并使用它来更新模型。但这不是安全的。因为您必须确保表单字段与模型字段匹配,或者添加验证模型中的字段存在。

bindModelToForm(model: any, form: FormGroup) {
    const keys = Object.keys(form.controls);
    keys.forEach(key => {
        form.controls[key].valueChanges.subscribe(
            (newValue) => {
                model[key] = newValue;
            }
        )
    });
}

我提供的服务的完整代码:
referenceFields -表示如果您有student: { name, group }之类的复杂字段,其中 group 是引用的模型,并且您只能从该模型中获取ID:< / p>

import { Injectable } from '@angular/core';
import { FormGroup } from "@angular/forms";

@Injectable({
    providedIn: 'root'
})
export class FormService {

    constructor() {
    }

    bindModelToForm(model: any, form: FormGroup, referenceFields: string[] = []) {
        if (!this.checkFieldsMatching(model, form)) {
            throw new Error('FormService -> bindModelToForm: Model and Form fields is not matching');
        }
        this.initForm(model, form);
        const formKeys = Object.keys(form.controls);
        formKeys.forEach(key => {
            if (referenceFields.includes(key)) {
                form.controls[key].valueChanges.subscribe(
                    (newValue) => {
                        model[key] = newValue.id;
                    }
                )
            } else {
                form.controls[key].valueChanges.subscribe(
                    (newValue) => {
                        model[key] = newValue;
                    }
                )
            }
        });
    }

    private initForm(model: any, form: FormGroup) {
        const keys = Object.keys(form.controls);
        keys.forEach(key => {
            form.controls[key].setValue(model[key]);
        });
    }

    private checkFieldsMatching(model: any, form: FormGroup): boolean {
        const formKeys = Object.keys(form.controls);
        const modelKeys = Object.keys(model);
        formKeys.forEach(formKey => {
            if (!modelKeys.includes(formKey)) {
                return false;
            }
        });
        return true;
    }
}