且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-10-10 21:35:22

请勿使用 [(ngModel)] !反应形式要好得多.它们使手动 ngModel 绑定变得过时,并且具有一些非常漂亮的内置功能,在本答案中,我仅介绍其中的几个.

Don't use [(ngModel)]! Reactive forms are much nicer. They make manual ngModel bindings obsolete, and they have some pretty sweet built-in features that only a couple of which I'm going to cover in this answer.

如果要绑定到诸如文本输入之类的表单控件,请使用以下模板语法:

If you're binding to a form control such as a text input, use this template syntax:

<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>
    <input type="text" formControlName="myRequiredField">
</ng-container>

(( field1 field2 subgroupName subfield2 myRequiredField 是与表单各部分相对应的任意控件和控件组名称,创建 FormGroup 对象时,请参见下文.)

(field1, field2, subgroupName, subfield2, and myRequiredField are all arbitrary control and control group names that correspond to parts of your form, see below when creating the FormGroup object.)

FormGroup 的模型的只读数据绑定在模板中的访问有所不同:

Read-only data bindings to the model of the FormGroup are accessed a little differently in your template:

{{ this.myFormGroup.get('field1').value }}
{{ this.myFormGroup.get('subgroupName.subfield2').value }}
<!-- Hint: use an array if you have field names that contain "." -->
{{ this.myFormGroup.get(['subgroupName', 'subfield2']).value }}

创建 FormGroup

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

Creating the FormGroup

In your component class, in constructor() (this should be before the template renders), use the following syntax to build a form group to talk to this form:

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

...
    public readonly myFormGroup: FormGroup;
...
    constructor(private readonly formBuilder: FormBuilder) {
        this.myFormGroup = this.formBuilder.group({
            field1: [],
            field2: [],
            subgroupName: this.formBuilder.group({
                subfield2: [],
            }),
            myRequiredField: ['', Validators.required],
        });
        this.retrieveData();
    }

用数据填充表单

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

Filling your form with data

If your component needs to retrieve data from a service as it loads, you must make sure it starts the transfer after the form has been built, then use patchValue() to put the data from your object into the FormGroup:

    private retrieveData(): void {
        this.dataService.getData()
            .subscribe((res: SomeDataStructure) => {
                // Assuming res has a structure like:
                // res = {
                //     field1: "some-string",
                //     field2: "other-string",
                //     subgroupName: {
                //         subfield2: "another-string"
                //     },
                // }
                // Values in res that don't line up to the form structure
                // are discarded. You can also pass in your own object you
                // construct ad-hoc.
                this.myFormGroup.patchValue(res);
            });
    }

从表格中获取数据

现在,假设您的用户单击了提交,现在您需要从表单中获取数据,然后通过服务将其 POST 返回到您的API.只需使用 getRawValue :

Getting data out of the form

Now, say your user clicks submit and now you need to get the data back out of your form and POST it back to your API thru a service. Just use getRawValue:

public onClickSubmit(): void {
    if (this.myFormGroup.invalid) {
        // stop here if it's invalid
        alert('Invalid input');
        return;
    }
    this.myDataService.submitUpdate(this.myFormGroup.getRawValue())
        .subscribe((): void => {
            alert('Saved!');
        });
}

所有这些技术消除了对任何 [(ngModel)] 绑定的需求,因为表单在 FormGroup 对象内维护了自己的内部模型.

All these techniques eliminate the need for any [(ngModel)] bindings, since the form maintains its own internal model inside the FormGroup object.