Angular动态表单组:不将表单输入绑定到表单组。

huangapple go评论62阅读模式
英文:

Angular dynamic form group: not binding form inputs to form groups

问题

Objective

我正在尝试在Angular中创建一个表单,根据从后端接收到的数组动态渲染一些字段。

假设表单中的三个可能输入是 ["one", "two", "three", "four"]

然后,根据此数组,应该呈现一个表单,并且表单组应该只包含接收到的数组中提到的输入字段。在我的情况下,我们只说:["one", "two", "three"]

Problem:

现在先不要考虑渲染部分,重点是创建表单组。

正如您可以在下面看到的那样,简单的代码尝试使用 addControl 方法动态向表单组添加控件。

当提交代码时,字段存在为{one: null, two: null, three: null}

我已经订阅了表单的 valueChanges 以打印出任何更改。

但是当更改字段 one 的输入时,没有触发任何事件,也没有打印任何内容。

此外,当提交时,对象似乎为{one: null, two: null, three: null},就好像没有发生任何更改。

我猜测某种方式,表单模板没有与组件中的代码绑定,但我无法弄清楚出了什么问题。

import 'zone.js/dist/zone';
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { bootstrapApplication } from '@angular/platform-browser';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';

@Component({
  selector: 'my-app',
  standalone: true,
  imports: [CommonModule],
  template: `
    <h1>Hello from {{name}}!</h1>
    <div>
      <div class="col-5 form-floating">
        <input formControlName="one"/>
        <label>One</label>
      </div>
    </div>
    <button (click)="submit()">SUBMIT</button>
  `,
})
export class App implements OnInit {
  name = 'Angular';
  array = ['one', 'two', 'three'];
  form!: FormGroup;

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.form = this.fb.group({});
    this.createForm();
  }

  createForm(): void {
    this.array.forEach((field: string) => {
      this.form.addControl(field, new FormControl(null));
    });

    this.form.valueChanges.subscribe((x) => {
      console.log(x);
    });
  }

  submit(): void {
    console.log(this.form.value);
  }
}

bootstrapApplication(App);

https://stackblitz.com/edit/angular-5thwux?file=src%2Fmain.ts

英文:

Objective

I am trying to create a form in angular that dynamically renders some fields based on an array that is received from the backend.

Let's say that the three possible inputs in the form are ["one", "two", "three", "four"].

Then depending on this array, a form should be rendered and the form group should only have inputs mentioned in the received array. In my case let us just say: ["one", "two", "three"].

Problem:

Let's forget the rendering part for now and focus on creating the form group.

As you can see below, the simple code tries to use addControl method to dynamically add controls to the form group.

When submitting the code, the fields are present as {one: null, two: null, three: null}.

I have subscribed to the valueChanges of the form to print out if anything changes.

But when the input of the field one is changed, there is no event fired and nothing is printed.

Furthermore, when submitted, the object seems to be {one: null, two: null, three: null} as if nothing changed.

My guess is that somehow, the form template is not being bound to the code in component.ts , but I cannot figure out what is going wrong.

import 'zone.js/dist/zone';
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { bootstrapApplication } from '@angular/platform-browser';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
@Component({
selector: 'my-app',
standalone: true,
imports: [CommonModule],
template: `
<h1>Hello from {{name}}!</h1>
<div>
<div class="col-5 form-floating">
<input formControlName="one"/>
<label>One</label>
</div>
</div>
<button (click)="submit()">SUBMIT</button>
`,
})
export class App implements OnInit {
name = 'Angular';
array = ['one', 'two', 'three'];
form!: FormGroup;
constructor(private fb: FormBuilder) {}
ngOnInit() {
this.form = this.fb.group({});
this.createForm();
}
createForm(): void {
this.array.forEach((field: string) => {
this.form.addControl(field, new FormControl(null));
});
this.form.valueChanges.subscribe((x) => {
console.log(x);
});
}
submit(): void {
console.log(this.form.value);
}
}
bootstrapApplication(App);

https://stackblitz.com/edit/angular-5thwux?file=src%2Fmain.ts

答案1

得分: 1

你忘记将其包含在一个 formGroup 中

<!--使用 *ngIf 避免初始错误-->
<form *ngIf="form" [formGroup]="form">
    <div class="col-5 form-floating">
        <input formControlName="one"/>
        <label>One</label>
    </div>
</form>

顺便说一下,你可以遍历数组

<form *ngIf="form" [formGroup]="form">
    <div *ngFor="let item of array" class="col-5 form-floating">
        <input [formControlName]="item"/>
        <label>One</label>
    </div>
</form>

甚至你的数组可以是一个对象数组,形式为 {label:...,field:...}

注意:如果你没有将其包含在 formGroup 中,控制台中没有错误是奇怪的。

英文:

You forgot enclosed in a formGroup

&lt;!--I use the *ngIf to avoid initial errors--&gt;
&lt;form *ngIf=&quot;form&quot; [formGroup]=&quot;form&quot;&gt;
&lt;div class=&quot;col-5 form-floating&quot;&gt;
&lt;input formControlName=&quot;one&quot;/&gt;
&lt;label&gt;One&lt;/label&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/form&gt;

BTW, you can iterate over the array

&lt;form *ngIf=&quot;form&quot; [formGroup]=&quot;form&quot;&gt;
&lt;div *ngFor=&quot;let item of array&quot; class=&quot;col-5 form-floating&quot;&gt;
&lt;input [formControlName]=&quot;item&quot;/&gt;
&lt;label&gt;One&lt;/label&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/form&gt;

Even your array can be an array of object in the way {label:...,field:...}

NOTE: It's strange you have no errors in console in you didn't enclosed in a formGroup

huangapple
  • 本文由 发表于 2023年5月22日 12:09:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76302989.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定