Devmix
Devmix

Reputation: 1848

How to add a clear icon on dropdown Angular Material?

I'm trying to add a clear icon on the right side of a dropdown (select component) in Angular material only if the user selects an option. If the user clicks on the "clear" icon I want to delete the value and reset the field. So far I have the dropdown and struggling on displaying the icon properly. Can anyone point me in the right direction? thanks in advance.

Here's my code:

<mat-form-field appearance="fill">
  <mat-label>Select a food</mat-label>
  <mat-select>
    <mat-option *ngFor="let food of foods" [value]="food.value">
      {{food.viewValue}}
    </mat-option>
    <mat-select-trigger>
        <button>
           <mat-icon>clear</mat-icon>
       </button>
    </mat-select-trigger>
  </mat-select>
</mat-form-field>

Here's LIVE DEMO

Upvotes: 0

Views: 7193

Answers (4)

Ahmed Khairy
Ahmed Khairy

Reputation: 61

You can use this way:

HTML:

<ng-template #clearRef>
  @if (value) {
    <svg
      class="text-danger"
      xmlns="http://www.w3.org/2000/svg"
      width="20"
      height="20"
      (click)="$event.stopPropagation(); control.reset()"
    >
      <path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
    </svg>
  }
</ng-template>

<ng-template #chevrondownRef>
  <svg class="chevron-down" [class.animate]="isPanelOpen" xmlns="http://www.w3.org/2000/svg" width="20" height="20">
    <path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
  </svg>
</ng-template>

CSS:

.mat-mdc-form-field-type-mat-select {
  .mat-mdc-form-field-infix {
    --mat-form-field-container-vertical-padding: 0;

    .mat-mdc-select-arrow-wrapper {
      flex-direction: row-reverse;
      gap: 0.5rem;
    }
  }
}

.chevron-down {
  transition: all 0.25s ease;
  transform: translate(-50%, -50%) rotate(0deg);

  &.animate {
    transform: translate(-50%, -50%) rotate(180deg);
  }
}

TS:

  • adding encapsulation: ViewEncapsulation.None,
  private vcr = inject(ViewContainerRef);

  @ViewChild(MatSelect) matSelect!: MatSelect;
  @ViewChild("clearRef") clearRef!: TemplateRef<HTMLElement>;
  @ViewChild("chevrondownRef") chevrondownRef!: TemplateRef<HTMLElement>;

  ngAfterViewInit(): void {
    //Called after ngAfterContentInit when the component's view has been initialized. Applies to components only.
    //Add 'implements AfterViewInit' to the class.
    const mdcSelectArrowWrapper = document.querySelector(".mat-mdc-select-arrow-wrapper");
    const mdcSelectArrow = this.matSelect._elementRef.nativeElement.querySelector(
      ".mat-mdc-select-arrow-wrapper .mat-mdc-select-arrow",
    ) as HTMLElement;

    mdcSelectArrowWrapper?.appendChild(this.vcr.createEmbeddedView(this.clearRef).rootNodes[0]);
    mdcSelectArrow.replaceChildren(this.vcr.createEmbeddedView(this.chevrondownRef).rootNodes[0]);
  }

Results: The material select which has a new arrow icon

Upvotes: 0

Zia Khan
Zia Khan

Reputation: 425

THE SOLUTION that worked fir me is given below.... using mat-select In component.ts file

import {Directive, HostListener} from "@angular/core";

@Directive({
    selector: "[click-stop-propagation]"
})
export class ClickStopPropagation
{
    @HostListener("click", ["$event"])
    public onClick(event: any): void
    {
        event.stopPropagation();
    }
}

In template call the function like this

(click)="onCLick($event)

Upvotes: 0

Devang Patel
Devang Patel

Reputation: 1843

You need to add ngModel on mat-select for two way binding to add selected value into it. Also add button as suffix of mat-select.

<mat-select [(ngModel)]="selectedFood">
    <mat-option *ngFor="let food of foods" [value]="food.value">
        {{ food.viewValue }}
    </mat-option>
</mat-select>
<button mat-button matSuffix *ngIf="selectedFood" mat-icon-button (click)="onClick($event)">
    <mat-icon>close</mat-icon>
</button>

On your component side you need to add following function to clear selected food value.

onClick(event: any) {
    this.selectedFood = "";
    event.stopPropagation();
}

event.stopPropagation() will stop mat select dropdown to be opened on cick of clean button.

Here is your working solution:

https://stackblitz.com/edit/angular-c7hgum-94nqyq

Upvotes: 8

zainhassan
zainhassan

Reputation: 1780

<mat-form-field appearance="fill">
    <mat-label>Select a food</mat-label>
    <mat-select [(ngModel)]="selectedFood">
        <mat-option *ngFor="let food of foods" [value]="food.value">
            {{food.viewValue}}
        </mat-option>
    </mat-select>
    <button mat-button *ngIf="selectedFood" matSuffix mat-icon-button aria-label="Clear" (click)="selectedFood=''">
    <mat-icon>close</mat-icon>
  </button>
</mat-form-field>

Upvotes: 0

Related Questions