Esteban Chornet
Esteban Chornet

Reputation: 1237

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?

Upvotes: 11

Views: 22825

Answers (7)

Moissane Hernandez
Moissane Hernandez

Reputation: 136

To fix the chip's display issue in material 16 or greater

:host {
  ::ng-deep .mat-mdc-select-value-text {
    white-space: normal;
  }
}

Upvotes: 0

Phil Mayfield
Phil Mayfield

Reputation: 248

Just updating with an example from Angular 17, things seem to work fine without custom styles.

https://stackblitz.com/edit/nucddw?file=src%2Fexample%2Fselect-multiple-example.ts,src%2Fexample%2Fselect-multiple-example.html

Upvotes: 0

Andrea Rosi
Andrea Rosi

Reputation: 121

To fix the issue with the wrong display of the chip list with Material 13 i added this to my css

.mat-select-trigger {
   height: fit-content;
}

Upvotes: 7

MoishyS
MoishyS

Reputation: 2882

MhagnumDw's answer broke since Material V13, can be fixed with the following CSS.

.mat-select-trigger{
   height: fit-content;
}

.mat-select-arrow-wrapper{
   align-self: start;
}

https://stackblitz.com/edit/angular-material-v9-mat-select-with-mat-chip-list-ufwxke?file=src%2Fstyles.scss%3AL16

Credit https://stackoverflow.com/a/72515815/10853425

Upvotes: 0

MhagnumDw
MhagnumDw

Reputation: 963

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

Upvotes: 30

JuNe
JuNe

Reputation: 1997

You can do this by pushing the selected values to a variable and read this variable in the mat-chip-list.

HTML:

<mat-form-field>
  <mat-label>Select an option</mat-label>
  <mat-select [(value)]="selected" multiple>
    <mat-option>None</mat-option>
    <mat-option value="option1">Option 1</mat-option>
    <mat-option value="option2">Option 2</mat-option>
    <mat-option value="option3">Option 3</mat-option>
  </mat-select>
</mat-form-field>
<mat-chip-list>
  <mat-chip *ngFor="let value of selected">{{value}}</mat-chip>
</mat-chip-list>

TS:

import {Component} from '@angular/core';

@Component({
  selector: 'my-example',
  templateUrl: 'my-example.html',
  styleUrls: ['my-example.css'],
})
export class MyExample {
  selected: string[] = [];
}

Upvotes: 1

Related Questions