Angular Material - How to customise style of selected option

3k views Asked by At

I am working on an Angular application using the Angular Material library.

component.html

<mat-select>
    <mat-option *ngFor="let option of options" [value]="option.value">
      <span> {{ option.name }} </span>
      <span class="colorful-badge-class"> {{ option.label }} </span>
    </mat-option>
</mat-select>

On the dropdown, the option works nicely as expected with each option having the option name and a coloured badge beside it. However, when the option is selected, the option is no longer styled inside the form control field.

In the inspected HTML, the selected field is shown as:

<span class="mat-select-min-line ng-star-inserted">option-name option-label</span> 

Not even respecting the original DOM structure of the option.

Is there a way to choose what shows up in the form control field after the option is selected (e.g. just showing option.name and not needing the label), or possibly style the selected field keeping the structure passed to the original <mat-option>?

Any help is appreciated since there seems to be no documentation on the <mat-option> component.

2

There are 2 answers

1
Yong Shun On

Work with <mat-select-trigger> element to customize the selected option text.

<mat-select
  [formControl]="selectedOption"
  (selectionChange)="onSelectOption($event)"
>
  <mat-select-trigger>
    <span class="red" *ngIf="selectedOptionObj">
      {{ selectedOptionObj.name }}
    </span>
  </mat-select-trigger>
  <mat-option *ngFor="let option of options" [value]="option.value">
    <span> {{ option.name }} </span>
    <span class="colorful-badge-class"> {{ option.label }} </span>
  </mat-option>
</mat-select>
  1. Create selectedOptionObj variable to store the selected option object.
  2. With selectionChange event to trigger onSelectOption method for storing selected option object by selected value.
selectedOptionObj: any;

onSelectOption(event: any) {
  let selectedValue = event.value;

  this.selectedOptionObj = this.options.find((x) => x.value == selectedValue);
}

Sample StackBlitz Demo


Reference

Select with custom trigger text

0
Igor Kurkov On

Even in 2024 in Angular Material v.17, there is still no ability to get the selected option in mat-select-trigger.

Also if you use someMethodWithArrayFindInside() in your HTML template, you will get in trouble with performance leaks, because you can use methods in the template only under onPush strategy. Otherwise, your method will fire whenever CD fires.

That's why I suggest using a simple pipe to get current selected option from formControl:

<mat-select
  [formControl]="myFormControl"
>
  <mat-select-trigger>
    <span>Your customized trigger value</span>
    {{ (myFormControl.value | selectedOptionPipe: options)?.viewValue || '' }}
  </mat-select-trigger>
...
</mat-select>

pipe:

@Pipe({
  name: 'selectedOptionPipe',
})
export class SelectedOptionPipe implements PipeTransform {
  public transform(value: any, options: CustomOption[]): CustomOption| null {
    return options.find((v) => v.value === value) || null;
  }
}