Search code examples
angularangular-material

Is it possible to use mat-select and mat-chips together?


I wanna know if it's possible have a "mix" of mat-select and mat-chip-list. In the chip-list, I want to show the selected options from mat-select.

If it is, how can I do it?


Solution

  • Yes, it is possible. You need to use <mat-select-trigger> within <mat-select>. Inside <mat-select-trigger> place <mat-chip-list>.

    In your HTML template you need something like:

    <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">{{topping}}</mat-option>
    
      </mat-select>
    </mat-form-field>
    
    <br/> <!-- only for debug -->
    {{ toppingsControl.value | json }}
    

    And in your ts:

    @Component({
      selector: 'select-multiple-example',
      templateUrl: 'select-multiple-example.html',
      styleUrls: ['select-multiple-example.css'],
    })
    export class SelectMultipleExample {
      toppingsControl = new FormControl([]);
      toppingList: string[] = ['Extra cheese', 'Mushroom', 'Onion', 'Pepperoni', 'Sausage', 'Tomato'];
    
      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);
        }
      }
    
    }
    

    Here is a complete example with Angular Material 9, but it works the same in version 6.

    I hope this helps!

    Demo