如何在 Angular 响应式表单中正确呈现动态表单?

How to render dynamic forms properly in Angular Reactive Forms?

我有一个 API 请求 returns JSON 数组,如下所示:

{
  "address": {
    "addressLine1": "499 Linden Boulevard",
    "addressLine2": "Apt 4b",
    "city": "Moraida",
    "province": "Kansas",
    "postalCode": "21763",
    "country": "USA"
  },
  "phones": [
    {
      "phoneNumber": "+1 (887) 502-2245",
      "phoneType": 3
    },
    {
      "phoneNumber": "+1 (823) 536-7452",
      "phoneType": 1
    }
  ],
  "email": "latti.sh@hotmail.com"
}

“phones”JSON 数组是动态的.. 意味着它可能有一个或多个项目或 none.. 我正在尝试使用 Dynamic Reactive Forms,所以我定义了我的表单组,如下所示

addressInfoForm = new FormGroup({
  addressLine1: new FormControl('', [Validators.required]),
  addressLine2: new FormControl('', []),
  city: new FormControl('', [Validators.required]),
  province: new FormControl('', []),
  postalCode: new FormControl('', [Validators.required]),
  country: new FormControl({ value: '', disabled: true }, [Validators.required]),
  email: new FormControl('', [Validators.email]),
  phones: this.fb.array([this.fb.control('')]),
});

当我在 onInit() 方法中得到 JSON 响应时,我将表单值设置如下:

this.addressInfoForm.setValue({
  addressLine1: this.clientIdentInfo.address.addressLine1,
  addressLine2: this.clientIdentInfo.address.addressLine2,
  city: this.clientIdentInfo.address.city,
  province: this.clientIdentInfo.address.province,
  postalCode: this.clientIdentInfo.address.postalCode,
  country: this.clientIdentInfo.address.country,
  email: this.clientIdentInfo.email,
  // how to set the phones
});

我确实像这样构建了 get phones() 和 AddPhone() 方法。

get phones() {
  return this.addressInfoForm.get('phones') as FormArray;
}

AddPhone() {
  this.phones.push(this.fb.control(''));
  this.phones.push(this.fb.control(''));
}

在我的 html 中,我正在尝试填充 phone 并能够通过 AddPhone() 方法添加新的 phone,如下所示:

<form *ngFor="let phone of phones.controls; let i=index;" 
   [formGroupName]="i" 
   formArrayName="phones">
        <mat-grid-list cols="4" rowHeight="90px" gutterSize="10px">
          <mat-grid-tile  [colspan]="1">
            <mat-form-field appearance="outline" class="form-field">
              <mat-label>Phone {{i + 1}}</mat-label>
              <input matInput class="input-field" formControlName="phoneNumber">
              <mat-icon matSuffix>local_phone</mat-icon>
            </mat-form-field>
          </mat-grid-tile>
          <mat-grid-tile>
            <mat-form-field appearance="outline" class="form-field">
              <mat-label>Phone Type</mat-label>
              <mat-select formControlName="phoneType">
                <mat-option *ngFor="let type of phoneTypes" [value]="type.phoneTypeId">
                  {{ type.phoneTypeName }}
                </mat-option>
              </mat-select>
            </mat-form-field>
          </mat-grid-tile>
        </mat-grid-list>
      </form>

不幸的是,这不起作用!有人可以帮助我以正确的方式实现这一目标吗?

您需要根据您的结果将 phone 控件添加到 phone 数组,并将值修补到 phones 格式数组。

   this.addressInfoForm.patchValue({
      addressLine1: result.address.addressLine1,
      addressLine2: result.address.addressLine1,
      city: result.address.city,
      province: result.address.province,
      postalCode: result.address.postalCode,
      country: result.address.country,
      email: result.email
    });

    for (let i = 0; i < result.phones.length - 1; i++) {
      this.AddPhone();
    }

    result.phones.forEach((item, index) => {
      this.phones.get(index.toString()).patchValue({
        phoneNumber: item.phoneNumber,
        phoneType: item.phoneType
      });
    });

这是您的解决方案的 stackblitz 示例: https://stackblitz.com/edit/angular-ivy-bhclwz?file=src/app/app.component.ts