【问题标题】:Angular Material MatChipList - how to use it on a Dynamic FormArray?Angular Material MatChipList - 如何在动态 FormArray 上使用它?
【发布时间】:2019-04-06 04:22:36
【问题描述】:

StackBlitz

这是我的 FormArray(变体):

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

我使用MatChips 来存储一个字符串数组。这个数组需要传递给options

<div formArrayName="variants" *ngFor="let item of productGroup.controls['variants'].controls; 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">
        <mat-chip-list #chipList>
          <mat-chip *ngFor="let opt of typesOptions" [selectable]="true"
                    [removable]="true" (removed)="removeOpt(opt)">
            {{opt}}
            <mat-icon matChipRemove>cancel</mat-icon>
          </mat-chip>
          <input placeholder="Conjunto de opções deste Tipo"
                  formControlName="options"
                  [matChipInputFor]="chipList"
                  [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
                  [matChipInputAddOnBlur]="true"
                  (matChipInputTokenEnd)="addOpt($event)">
        </mat-chip-list>
      </mat-form-field>
    </div>
  </div>
  <div class="row">
    <a href="javascript:" (click)="addItem()"> Add Variants </a>
    <a href="javascript:" (click)="removeItem(i)" *ngIf="i > 0"> Remove Variants </a>
  </div>
</div>

方法如下:

// Dynamic Methods
  addItem(): void {
    this.variantsArray = this.productGroup.get('variants') as FormArray;
    this.variantsArray.push(this.fb.group({
      type: '',
      options: ''
    }));
  }
  removeItem(index: number) {
    this.variantsArray.removeAt(index);
  }

// MatChip Methods
  addOpt(item: number, event: MatChipInputEvent): void {
    const input = event.input;
    const value = event.value;
    // Add our fruit
    if ((value || '').trim()) {
      this.typesOptions.push(value.trim());
    }
    // Reset the input value
    if (input) {
      input.value = '';
    }
  }
  removeOpt(opt: string): void {
    const index = this.typesOptions.indexOf(opt);
    if (index >= 0) {
      this.typesOptions.splice(index, 1);
    }

我已成功将动态字段添加到我的variants formArray。但是 MatChipList 对于每个动态字段都是相同的。我还需要使MatChipList 动态化。有没有办法做到这一点?比如更改&lt;mat-chip-list #chipList+i&gt; 或类似的东西。

编辑:StackBlitz

【问题讨论】:

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


    【解决方案1】:

    我不确定 dom 引用变量 #chiplist 是否存在问题。看起来 matChipList 由 typesOptions 数组支持,但您只有一个数组。因此,每次添加 matChipList 组件时,它仍然由与所有其他组件相同的数组支持。你需要有一个typesOptions数组,一个数组数组。然后,当您添加项目时,您还将一个新的子数组推送到 typesOptions(并且类似地为 removeItem 删除一个)。

    我没有编写代码,只是查看代码的建议。

    编辑 - 根据 James 的 stackblitz 编写解决方案。

    https://stackblitz.com/edit/angular-3od6rd-jkidxf

    注意我没有详细研究删除变体是如何组合在一起的,理想情况下,我可能想使用键/值对来跟踪变体选项,使用 dom 输入元素 id 作为键(在MatChipInputEvent),而不是依赖于外部循环索引。

    stackblitz 中的一些代码:

    export class ChipsOverviewExample {
      productGroup: FormGroup;
      variantsArray: FormArray;
      typesOptionsArray: string[][] = [];
      readonly separatorKeysCodes: number[] = [ENTER, COMMA];
    
      constructor(private fb: FormBuilder) {}
    
      ngOnInit() {
        this.productGroup = this.fb.group({
          name: '',
          variants: this.fb.array([
            this.fb.group({
              type: '',
              options: ''
            })
          ]),
        });
        this.typesOptionsArray.push([]);
      }
    
      saveProduct(form: FormGroup) {
        console.log(form);
      }
    
      // Add new item to FormArray
      addItem(): void {
        this.variantsArray = this.productGroup.get('variants') as FormArray;
        this.variantsArray.push(this.fb.group({
          type: '',
          options: ''
        }));
    
        this.typesOptionsArray.push([]);
      }
    
      removeItem(index: number) {
        this.variantsArray.removeAt(index);
      }
    
      addOpt(event: MatChipInputEvent, index: number): void {
        const input = event.input;
        const value = event.value;
        // Add our fruit
        if ((value || '').trim()) {
          this.typesOptionsArray[index].push(value.trim());
    
        }
        // Reset the input value
        if (input) {
          input.value = '';
        }
      }
    
      removeOpt(opt: string, index: number): void {
        const optIndex = this.typesOptionsArray[index].indexOf(opt);
        if (optIndex >= 0) {
          this.typesOptionsArray[index].splice(optIndex, 1);
        }
      }
    }
    

    【讨论】:

    • this.typesOptions.push(value.trim()); this.typesOptionsArray.push(this.typesOptions);如何使用这个数组来停止重复值?
    • James 如果您提出了一个有效的 StackBlitz 来说明问题,您应该很快就能得到有效的答案。也许 fork Angular 示例之一,stackblitz.com/angular/…
    【解决方案2】:

    尝试将formGroup作为一个新组件并输入formGroup(不是formGroupName)。

    <div formArrayName="variants" *ngFor="let item of productGroup.controls['variants'].controls; let i = index;">
      <variant [varientGroup]="item"><varient>
      <div class="row">
        <a href="javascript:" (click)="addItem()"> Add Variants </a>
        <a href="javascript:" (click)="removeItem(i)" *ngIf="i > 0"> Remove Variants </a>
      </div>
    </div>
    

    各种组件.html

    <div [formGroup]="varientGroup">
     <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">
          <mat-chip-list #chipList>
            <mat-chip *ngFor="let opt of typesOptions" [selectable]="true"
                    [removable]="true" (removed)="removeOpt(opt)">
              {{opt}}
              <mat-icon matChipRemove>cancel</mat-icon>
            </mat-chip>
            <input placeholder="Conjunto de opções deste Tipo"
                  [matChipInputFor]="chipList"
                  [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
                  [matChipInputAddOnBlur]="true"
                  (matChipInputTokenEnd)="addOpt($event)">
          </mat-chip-list>
        </mat-form-field>
      </div>
    </div>
    

    在varient.component.ts中

    @Input()varientGroup: FormGroup
    

    【讨论】:

    • 这是最干净的方法。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2019-01-04
    • 1970-01-01
    • 2018-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多