📜  如何限制 mat-chip-list 多选中的重复选择 (1)

📅  最后修改于: 2023-12-03 15:09:18.032000             🧑  作者: Mango

如何限制 mat-chip-list 多选中的重复选择

mat-chip-list 是 Angular Material 中常用的多选组件,但是它默认是允许重复选择的,这可能不是我们想要的行为。本文将介绍如何限制 mat-chip-list 多选中的重复选择。

解决方案

我们可以使用 Angular 自带的 FormControl 来实现限制 mat-chip-list 多选中的重复选择。具体步骤如下:

  1. 在组件中定义一个表单控件:

    form = new FormGroup({
      chips: new FormArray([]),
    });
    
  2. 在模板中使用 mat-chip-list 组件,并将其绑定到表单控件中:

    <mat-form-field>
      <mat-chip-list #chipList aria-label="Fruit selection" formControlName="chips">
        <mat-chip *ngFor="let chip of chips" [value]="chip">{{ chip }}</mat-chip>
      </mat-chip-list>
    </mat-form-field>
    
  3. 定义一个方法来处理 mat-chip-remove 事件,当用户移除一个选项时,将其从表单控件中删除:

    onRemove(chip: string): void {
      const chips = this.form.controls.chips as FormArray;
      const index = chips.controls.findIndex(control => control.value === chip);
      if (index >= 0) {
        chips.removeAt(index);
      }
    }
    
  4. 定义一个方法来处理 mat-chip-input 事件,当用户输入一个选项时,将其添加到表单控件中:

    onInput(event: MatChipInputEvent): void {
      const value = (event.value || '').trim();
      if (value) {
        const chips = this.form.controls.chips as FormArray;
        if (chips.value.indexOf(value) === -1) {
          chips.push(new FormControl(value));
        }
      }
      event.chipInput!.clear();
    }
    
  5. 最后,在 ngOnInit 生命周期钩子中,订阅表单控件中的值变化,并使用 distinctUntilChanged 运算符来过滤重复值:

    ngOnInit(): void {
      this.form.controls.chips.valueChanges
        .pipe(distinctUntilChanged())
        .subscribe(values => {
          // Do something with the selected values
        });
    }
    
示例代码
import { Component } from '@angular/core';
import { FormArray, FormControl, FormGroup } from '@angular/forms';
import { MatChipInputEvent } from '@angular/material/chips';
import { Observable } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';

@Component({
  selector: 'app-chip-list',
  templateUrl: './chip-list.component.html',
  styleUrls: ['./chip-list.component.css'],
})
export class ChipListComponent {
  chips: string[] = ['Apple', 'Banana', 'Orange'];

  form = new FormGroup({
    chips: new FormArray([]),
  });

  ngOnInit(): void {
    this.form.controls.chips.valueChanges
      .pipe(distinctUntilChanged())
      .subscribe(values => {
        // Do something with the selected values
        console.log(values);
      });
  }

  onRemove(chip: string): void {
    const chips = this.form.controls.chips as FormArray;
    const index = chips.controls.findIndex(control => control.value === chip);
    if (index >= 0) {
      chips.removeAt(index);
    }
  }

  onInput(event: MatChipInputEvent): void {
    const value = (event.value || '').trim();
    if (value) {
      const chips = this.form.controls.chips as FormArray;
      if (chips.value.indexOf(value) === -1) {
        chips.push(new FormControl(value));
      }
    }
    event.chipInput!.clear();
  }
}
<mat-form-field>
  <mat-chip-list #chipList aria-label="Fruit selection" formControlName="chips">
    <mat-chip *ngFor="let chip of chips" [value]="chip">{{ chip }}</mat-chip>
    <input matInput [matChipInputFor]="chipList" (matChipInput)="onInput($event)" />
  </mat-chip-list>
</mat-form-field>