如何在 angular material 多 select 复选框和芯片组件中显示 selected 名称

How to show selected name in angular material multi select checkbox and chips component

我在 angular material 芯片上使用多 select 复选框。我有带有名称和 ID 的数组对象,如果必须将用户 select 选项和 ID 发送到后端,则应该显示名称。当我分配 [value]="topping.id" 时,它显示 selected id 而不是名称。当用户 select 选项时,如何在 UI 中显示名称并将 ID 保留在 formControl 中?我在这里添加了演示 link。

图 1:当前结果

图 2:预期结果

Demo

app.component.html

<mat-form-field>
<mat-label>Toppings</mat-label>
<mat-select [formControl]="toppingsControl" multiple>
   <mat-select-trigger>
      <mat-chip-list>
         <mat-chip
         *ngFor="let topping of toppingsControl.value"
         [removable]="true"
         (removed)="onToppingRemoved(topping)">
         {{ topping }}
         <mat-icon matChipRemove>cancel</mat-icon>
         </mat-chip>
      </mat-chip-list>
   </mat-select-trigger>
   <mat-option *ngFor="let topping of toppingList" [value]="topping.id">
     {{topping.name}}
   </mat-option>
</mat-select>

app.component.ts

toppingsControl = new FormControl([]);

toppingList: any[] = [
  { id: 1, name: 'Extra cheese' },
  { id: 2, name: 'Mushroom' },
  { id: 3, name: 'Onion' },
  { id: 4, name: 'Sausage' }
];

 onToppingRemoved(topping: string) {
    const toppings = this.toppingsControl.value as string[];
    this.removeFirst(toppings, topping);
    this.toppingsControl.setValue(toppings); // To trigger change detection
  }

  private removeFirst<T>(array: T[], toRemove: T): void {
    const index = array.indexOf(toRemove);
    if (index !== -1) {
      array.splice(index, 1);
    }
  }

当前结果(图片 1):

预期结果(图 2):

  1. 列表项

问题出在下面这行代码:

<mat-option *ngFor="let topping of toppingList" [value]="topping.id">

您告诉 angular 使用 id 作为表单控件值的值。一种解决方案是不只使用 id,而是将这些 id 映射到顶部对象本身。然后您的控件使用的是顶部对象,而不仅仅是一个数字。这是您需要更改的代码:

  <mat-chip
          *ngFor="let topping of idsToToppings(toppingsControl.value)"
          [removable]="true"
          (removed)="onToppingRemoved(topping.id)"
        >
          {{ topping.name }}

并在您的组件中添加以下方法:

  idsToToppings(ids: number[]) : any[] {
    return ids.map((id) => {
      return this.toppingList.find((t) => t.id == id);
    });
  }