【问题标题】:Dynamically add new fields on a click event?在点击事件上动态添加新字段?
【发布时间】:2019-04-06 02:51:19
【问题描述】:

这是我的表单组:

this.productGroup = this.fb.group({
  name: ['', Validators.compose([Validators.required, Validators.maxLength(80)])],
  desc: ['', Validators.maxLength(3000)],
  category: ['', Validators.required]
  variants: this.fb.array([
    this.fb.group({
      type: '',
      options: ''
    })
  ])
});

用户单击按钮后,我需要动态添加type 和options 控制字段。用户输入后 FormArray 应如下所示: [ {type: 'size', options: 'Small', 'Big'}, {type: 'color', options: 'red', 'blue, 'yellow'}, ... ].

这是我想要做的:

// Add new item to FormArray
addItem(): void {
  this.variantsArray = this.productGroup.get('variants') as FormArray;
  this.variantsArray.push(this.fb.group({
    type: '',
    options: ''
  }));
}

// Template
<form [formGroup]="productGroup">
  // inputs...
  <div formArrayName="variants" *ngFor="let item of productGroup.controls['variants']; let i = index;">
      <div [formGroupName]="i">
        <div class="row">
          <mat-form-field class="col-12">
            <input formControlName="type">
          </mat-form-field>
        </div>
        <div class="row">
          <mat-form-field class="col-12">
            <input formControlName="options">
          </mat-form-field>
        </div>
      </div>
      <div class="row">
        <a href="javascript:" (click)="addItem()"> Adicionar Variante </a>
        <a href="javascript:" (click)="removeItem(i)" *ngIf="i > 0"> Remover Variante </a>
      </div>
    </div>
</form>

如何让它发挥作用?

【问题讨论】:

  • 你怎么能像{type: 'size', options: 'Small', 'Big'} 显示的那样存储数据,这甚至不是像属性options: 'Small', 'Big' 这样的有效javascript 对象。任何一个选项属性都应该是一个数组,否则你会得到长字符串
  • 我将使用一个字符串数组将数据直接传递给我的组件上的这个 FormControl。更准确地说,我使用MatChipInput 将值传递给这个字符串数组。我正在尝试为输入获得一个通用的工作解决方案,以便我可以在我的代码上实现。

标签: javascript angular typescript angular-material angular-reactive-forms


【解决方案1】:

我不知道你想要达到什么目标,但我想我遇到了你的问题。

以下代码:

variants: this.fb.array([
    this.fb.group({
      type: '',
      options: ''
    })
  ])

不会生成数组,因此您不能使用 *ngFor 对其进行迭代。

如果你深入了解它,你会发现

productGroup.controls['variants']

具有控件的属性。

所以只需将*ngFor 更改为:

*ngFor="let item of productGroup.controls['variants'].controls; let i = index;"

你应该没事的。

【讨论】:

  • 谢谢! Angular Language Service 扩展无法正确加载表单组的某些属性。另外假设我将一个字符串数组直接传递给options(我正在使用一些“芯片”来添加字符串)......如何确保我将字符串数组添加到正确的表单数组索引?
  • 如果有人可以帮助我...提出一个新问题:link
【解决方案2】:

要在响应式表单中动态添加 formElemnt,您需要首先创建表单元素或表单组,并将其推送到该字段的原始表单中。

EX:我有一个如下所示的 customerForm

this.customerForm = this.fb.group({
  firstName: ['', [Validators.required, Validators.minLength(3)]],
  lastName: ['', [Validators.required, Validators.maxLength(50)]],
  emailGroup: this.fb.group({
    email: ['', [Validators.required, Validators.email]],
    confirmEmail: ['', Validators.required],
  }, { validator: emailMatcher }),
  phone: ''
  addresses: this.fb.array([this.createAddress()])
});

点击视图中的添加地址后,我可以调用组件中的函数,将新地址推送到表单中的地址数组。

  addAddress(): void {
   this.addresses.push(this.createAddress());
  }

 createAddress(): FormGroup {
   return this.fb.group({
      street1: ['', Validators.required],
      street2: '',
      city: '',
      state: '',
      zip: ''
   });
 }

在您看来,您可以遍历此地址数组并显示地址。最初它不会显示,因为数组值将为空!希望对您有所帮助。

【讨论】:

  • 如果你的FormArray里面没有FormGroup怎么办?
  • 喜欢这个addresses: this.fb.array([]),你想在里面传递[ 'string1', 'string2' ]
  • 在这种情况下,您可以使用 new FormControl() 在表单上创建新控件:例如:this.customerForm.addControl('newControl', new FormControl(' ', Validators.required ) );
  • 你能看看这里吗? Stackblitz 和 Question。我正在尝试这样的事情来将这些控件添加到特定的嵌套表单组中(组 -> 动态数组 -> 组 -> 数组):this.productGroup.controls['variants']['options'].push(new FormControl(type));
  • this.productGroup = this.fb.group({ name: '', variants: this.fb.array([ this.fb.group({ type: '', options: this.fb.array([]) }) ]) })
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 2017-01-18
  • 1970-01-01
  • 2019-02-11
相关资源
最近更新 更多