代码之家  ›  专栏  ›  技术社区  ›  Mouad Ennaciri

角度/反应式表单-添加或删除表单控件列表-绑定模板(带演示)

  •  2
  • Mouad Ennaciri  · 技术社区  · 6 年前

    我有一个 matSelect 因为我可以从1到10之间选择一个数字,根据数字,我必须显示相同的数字 matInput 用一个字母表示。在选择中默认选择的数字是1(因此我们有一个 矩阵输入 默认情况下)

    <mat-form-field>
      <mat-select placeholder="Number of winners to reward" [value]="selected" (selectionChange)="selectNumber($event)">
        <mat-option *ngFor="let emailNumber of totalEmailsNumber" [value]="emailNumber">
          {{ emailNumber }}
        </mat-option>
      </mat-select>
    </mat-form-field>
    
    <div formArrayName="mails">
      <mat-form-field *ngFor="let email of form.get('mails').controls; let i = index">
        <textarea matInput [formControlName]="i"></textarea>
      </mat-form-field>
    </div>
    

    添加第一个 MatInput 我愿意:

    this.form.controls['mails'] = this.fb.array(this.emailsNumber.map(() => new FormControl('', Validators.required)));
    

    这是可行的,但我无法管理逻辑来添加另一个 FormControl 或者删除它,例如,如果用户在选择中选择10,然后将其更改为4, 并管理模板中的绑定。

    我还想知道的是 *ngFor="let email of form.get('mails').controls 是一种好的做法吗?


    这里有一个 Minimal StackBlitz Demo 与之合作

    2 回复  |  直到 6 年前
        1
  •  2
  •   SiddAjmera    6 年前

    尝试一下:

    import { Component, OnInit } from '@angular/core';
    import { FormArray, FormBuilder, Validators } from '@angular/forms';
    
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html'
    })
    export class AppComponent implements OnInit {
      form: FormGroup;
      totalEmailsNumber: number[];
    
      constructor(private fb: FormBuilder) {
      }
    
      ngOnInit() {
        this.totalEmailsNumber = this.createCustomLengthArray(10);
        this.form = this.fb.group({
          mails: this.fb.array([])
        });
      }
    
      get mails() {
        return (<FormArray>this.form.controls['mails']);
      }
    
      selectNumber(emailNumbers) {
        const difference = this.mails.length - emailNumbers;
        difference > 0 ? this.removeMails(difference) : this.addMails(difference);
      }
    
      removeMails(difference) {
        this.createCustomLengthArray(difference)
          .forEach(item => this.mails.removeAt(this.mails.length - 1));
      }
    
      addMails(difference) {
        this.createCustomLengthArray(difference)
          .forEach(
            item => {
              this.mails.push(this.fb.control(null, Validators.required));
            }
          );
      }
    
      createCustomLengthArray(length) {
        return (new Array(Math.abs(length)))
          .fill(null)
          .map((item, index) => index + 1);
      }
    }
    

    在模板中:

    <form [formGroup]="form">
        <mat-form-field>
            <mat-select 
              placeholder="Number of winners to reward" 
              [value]="selected" 
              (selectionChange)="selectNumber($event.value)">
                <mat-option 
                  *ngFor="let emailNumber of totalEmailsNumber" 
                  [value]="emailNumber">
                  {{ emailNumber }}
                </mat-option>
            </mat-select>
        </mat-form-field>
    
        <div formArrayName="mails">
            <mat-form-field 
              *ngFor="let email of form.controls['mails'].controls; let i = index">
                <textarea 
                  matInput 
                  [formControlName]="i">
          </textarea>
        </mat-form-field>
      </div>
    </form>
    

    这里有一个 Working Sample StackBlitz 为了你的食物。

        2
  •  2
  •   AT82    6 年前

    我们可以使用simple for循环并使用 push removeAt (取索引)作为形式安排。不要尝试 splice ,不起作用;)

    你也不想用 (selectionChange)="selectNumber($event)" 因为那会被解雇两次。代替使用 valueChange :

    <mat-form-field>
      <mat-select (valueChange)="selectNumber($event)">
        <mat-option *ngFor="let emailNumber of totalEmailsNumber" [value]="emailNumber">
          {{ emailNumber }}
        </mat-option>
      </mat-select>
    </mat-form-field>
    

    然后 selectNumber() 可能如下所示:

    selectNumber(value) {
      let formArr = this.form.get('mails') as FormArray;
      // user has chosen less fields than already exists
      if (formArr.controls.length > value) {
        const toRemove = formArr.controls.length - value;
        for (let i = 0; i < toRemove; i++ ) {
          // remove last element
          formArr.removeAt(formArr.length - 1);
        }
      } else {
        const addFields = value - formArr.controls.length;
        for (let i = 0; i < addFields; i++) {
          formArr.push(new FormControl(''));
        }
      }
    }
    

    StackBlitz

    至于最后一个问题…

    *ngFor="let email of form.get('mails').controls
    

    非常好!我用它,或者是吸气剂。