javascript - Angular Material MatChipList - 如何在动态 FormArray 上使用它?

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

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 中表单数组。然而MatChipList对于每个动态字段都是相同的。我需要做MatChipList动态也是如此。有办法实现这一点吗?喜欢改变<mat-chip-list #chipList+i>或类似的东西。

编辑:StackBlitz

最佳答案

我不确定 dom 引用变量 #chiplist 是问题所在。看起来 matChipList 由 typesOptions 数组支持,但你只有一个数组。因此,每次添加 matChipList 组件时,它仍然由与所有其他组件相同的数组支持。您需要有一个 typesOptions 数组,一个数组的数组。然后,当您 addItem 时,您还将一个新的子数组推送到 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);
    }
  }
}

关于javascript - Angular Material MatChipList - 如何在动态 FormArray 上使用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53109833/

相关文章:

angular - ngrx:在自定义对话框中等待确认或取消

typescript - 为什么 `map()` 返回类型不保持与输入相同数量的值?

javascript - Typescript d3 - 类型 'pie' 上不存在属性 'typeof d3'

javascript - Cordova Android 后退按钮事件不会触发

javascript - 如何将数据插入到对象数组中javascript

Angular 2 在发出事件时调用函数/方法

Angular 圆形模块导入

javascript - 中心动态 Angular 形式

javascript - 如何在 Chrome、Firebug 和 Firefox 控制台中显示数组的所有条目?

typescript - 网页包 ts-loader : change tsconfig filename