【问题标题】:angular 11 form dynamic data bindingangular 11 表单动态数据绑定
【发布时间】:2021-01-28 16:03:04
【问题描述】:

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

<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>

【问题讨论】:

  • 你能试试@rxweb/reactive-form-validators的rxforms吗

标签: angular angular-forms


【解决方案1】:

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

  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

【讨论】:

  • 谢谢你,但我刚刚检查了演示;当我增加作业计数器输入时,它似乎根本没有添加任何输入。我错过了什么吗?
  • 你输入一个数字然后回车,我相信这是大多数用户的期望
  • 哦,我明白了。按回车可能不适合手机?它似乎在累积计数器;例如如果我先输入3,则将其更改为2;它增加了另外 2 行。但我猜应该很容易调整。
  • 查看上面的修改,我相信它可以像你描述的那样工作,但对我来说我不会这样做
【解决方案2】:

您可以使用FormArray 来动态创建控件。监听 JobCounter 元素的 change 事件,然后您可以迭代并将 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,你也可以玩here

【讨论】:

  • 我仍在试图弄清楚它是如何工作的,但在示例中,即使减少工作计数器,它似乎总是增加工作名称和薪水输入。此外,当作业计数器增加一时,它似乎添加了两对(即四个输入)。
  • @stt106,以上一,不完整。它只是演示了基于计数器添加工作名称和薪水输入。请通过netbasal.com/…
  • @stt106,这是另一种方法stackblitz.com/edit/…
猜你喜欢
  • 2021-06-21
  • 2021-07-02
  • 1970-01-01
  • 1970-01-01
  • 2017-02-17
  • 1970-01-01
  • 2018-12-10
  • 2017-11-07
  • 2022-01-06
相关资源
最近更新 更多