angular 11 表单动态数据绑定

angular 11 form dynamic data binding

我有一个表单,其中有一对输入,一个用于名称,一个用于数字。所需的此类对的数量取决于用户输入,例如如果用户输入 5,它将生成 5 个这样的对。到目前为止,我可以使 UI 部分正常工作,例如它可以动态生成所需的对。问题是那些动态生成的输入对的数据绑定。因为它们是表单的一部分,所以我不能使用 [(ngModel)]。我尝试使用 FormControlName 但由于每个输入对的动态特性,它不起作用;似乎每个 FormControl 都必须在组件初始化时创建。窗体中的其他控件未显示。 我有一种感觉,也许我以错误的方式处理这个问题,有没有 'angular' 的方法来做到这一点?

<form [formGroup]="projectForm">
        <div>
            Enter the number of jobs:<input type="number" formControlName="jobCounter2"><br>
            <ng-container *ngFor="let i of [].constructor(projectForm.value.jobCounter2); let j = index">
                <div>
                    <ng-container style="width: 2px;">
                        <input type="text" placeholder="job name" formControlName="jobNames2[j]">
                    </ng-container>
                    <ng-container style="width: 1px">
                        <input type="number" placeholder="job salary e.g. 3.4" formControlName="jobSalary2[j]">
                    </ng-container>
                </div>
            </ng-container>
        </div> 
    </form>

您可以使用FormArray动态创建控件。监听 JobCounter 元素的变化事件然后你可以迭代并添加 FormControl 到 Jobs 数组。

import {
  Component,
  OnInit,
  VERSION
} from "@angular/core";
import {
  Form,
  FormArray,
  FormBuilder,
  FormGroup
} from "@angular/forms";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {
  projectForm: FormGroup;

  constructor(private formBuilder: FormBuilder) {}

  ngOnInit(): void {
    this.projectForm = this.formBuilder.group({
      jobCounter: [],
      jobs: this.formBuilder.array([]) //<=== Create Empty array
    });
  }

  onJobCounterChange(value) {
    value = Number(value);

    // Create the desired group based on user input
    for (let i = 0; i < value; i++) {
      let fb = this.formBuilder.group({
        name: [""],
        salary: [""]
      });
      (this.projectForm.controls.jobs as FormArray).push(fb);
    }
  }

  onSubmit() {
    console.log(this.projectForm.value);
  }
}
<form [formGroup]="projectForm" (ngSubmit)="onSubmit()">
  <div>
    Enter the number of jobs:
    <input type="number" formControlName="jobCounter" (change)="onJobCounterChange(projectForm.controls.jobCounter.value)"><br>
    <ng-container formArrayName="jobs">
      <div *ngFor="let job of projectForm.get('jobs')['controls']; let j = index" [formGroupName]="j">>
        <ng-container style="width: 2px;">
          <input type="text" placeholder="job name" formControlName="name">
        </ng-container>
        <ng-container style="width: 1px">
          <input type="number" placeholder="job salary e.g. 3.4" formControlName="salary">
        </ng-container>
      </div>
    </ng-container>

    <button>Show Values</button>
  </div>
</form>

Working Example, You can also play here

我认为您的方法可以改进以获得更好的用户体验,请考虑一下

  1. 与您的方法相同,用户可以添加更多字段但不将此值绑定到表单
  2. 包括一个删除按钮

这就是您的 TS 文件的样子

  projectForm = this.formBuilder.group({
    jobs: this.formBuilder.array([])
  });

  get jobs() {
    return this.projectForm.get("jobs") as FormArray;
  }
  deleteJobField(i) {
    this.jobs.controls.splice(i, 1);
    this.jobs.updateValueAndValidity()
  }
  addJobField($event) {
    $event.preventDefault();
    console.log( Array(this.additionalJobFields))
    Array(this.additionalJobFields).fill(1).forEach(() => {
      this.jobs.push(
        this.formBuilder.group({
          name: "",
          salary: 0
        })
      );
    });
    this.additionalJobFields = null;
  }
  additionalJobFields = null;

在你的 html

<form [formGroup]="projectForm" (ngSubmit)="onSubmit()">
    <div>
        <ng-container formArrayName="jobs">
            <div *ngFor="let job of jobs.controls; let j = index" [formGroupName]="j">>
                <ng-container style="width: 2px;">
                    <input type="text" placeholder="job name" formControlName="name">
                    </ng-container>
                    <ng-container style="width: 1px">
                        <input type="number" placeholder="job salary e.g. 3.4" formControlName="salary">

            <button (click)='deleteJobField(j)' type="button">DEL</button>
                    </ng-container>
            </div>
        </ng-container>

    <button>Show Values</button>
    </div>
        Add More Jobs:<input type="number" (keydown.enter)="addJobField($event)" [(ngModel)]="additionalJobFields"  [ngModelOptions]="{standalone: true}"><br>
</form>
<pre>{{ projectForm.value | json }}</pre>

基本思路是,当用户在输入字段中输入一个值以添加更多职位并按下回车键时,我们会更新表单数组中的字段数。

我们还针对每个输入类别添加了一个删除按钮,并在单击时更新表单数组

See this demo