1

I have custom Mat Auto Complete in Angular project. It has 2 suffixes, Clear and Dropdown buttons. When I click on clear button code this.myControl.reset('', { emitEvent: true }); resets the input value. But the dropdown panel does not open. I tried to use following formats and none worked

  1. this.myControl.reset();
  2. this.myControl.reset('', { emitEvent: true });
  3. this.myControl.patchValue('');

StackBlitz Demo

autocomplete-display-example.ts

.......

 clearInput() {
    this.arrowIcon = "arrow_drop_down";
    this.myControl.reset('', { emitEvent: true });
  }

......

autocomplete-display-example.html

<form class="example-form">
 <mat-form-field class="example-full-width">
   <mat-label>Assignee</mat-label>
   <input
     type="text"
     matInput
     [formControl]="myControl"
     [matAutocomplete]="auto"

   />
   <div matSuffix style="display:flex">
     <button
       *ngIf="myControl!==undefined && myControl.value!==null && myControl?.value!==''"
       mat-icon-button
       aria-label="Clear"
       (click)="clearInput()"
       type="button"
     >
       <mat-icon>clear</mat-icon>
     </button>

     <button mat-icon-button aria-label="Clear" type="button">
       <mat-icon>{{arrowIcon}}</mat-icon>
     </button>
   </div>

   <mat-autocomplete #auto="matAutocomplete" [displayWith]="displayFn" (opened)="arrowIcon='arrow_drop_up'"
     (closed)="arrowIcon='arrow_drop_down'" (optionSelected)="arrowIcon='arrow_drop_down'">
     <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
       {{option.name}}
     </mat-option>
   </mat-autocomplete>
 </mat-form-field>
</form>

<!-- Copyright 2020 Google LLC. All Rights Reserved.
   Use of this source code is governed by an MIT-style license that
   can be found in the LICENSE file at http://angular.io/license -->
Pavan Jadda
  • 4,306
  • 9
  • 47
  • 79

2 Answers2

5

Okay, when I click on Clear icon, it resets the form control and also closes the panel. To fix this we can open the panel manually. Inject the MatAutocompleteTrigger to the method along with event

See the updated StackBlitz Demo.

  openPanel(evt: any, trigger: MatAutocompleteTrigger): void {
    evt.stopPropagation();
    this.myControl?.reset();
    trigger.openPanel();
    this.inputAutoComplete?.nativeElement.focus();
  }

Add #trigger="matAutocompleteTrigger" to the input and pass this to button click() method

autocomplete-display-example.html


<form class="example-form">
  <mat-form-field class="example-full-width">
    <mat-label>Assignee</mat-label>
    <input #inputAutoComplete
           [formControl]="myControl"
           [matAutocomplete]="auto"
           #trigger="matAutocompleteTrigger"
           matInput
           type="text"
    />

    <div matSuffix style="display:flex">
      <button
        (click)="openPanel($event, trigger)"
        *ngIf=" myControl?.value!==null && myControl?.value!==''"
        aria-label="Clear"
        mat-icon-button
        type="button"
      >
        <mat-icon>clear</mat-icon>
      </button>

      <button aria-label="Clear" mat-icon-button type="button">
        <mat-icon>{{arrowIconSubject.getValue()}}</mat-icon>
      </button>
    </div>

    <mat-autocomplete #auto="matAutocomplete" (closed)="arrowIconSubject.next('arrow_drop_down')"
      (opened)="arrowIconSubject.next('arrow_drop_up')" (optionSelected)="arrowIconSubject.next('arrow_drop_down')"
      [displayWith]="displayFn">
      <mat-option *ngFor="let option of filteredOptions | async " [value]="option">
        {{option.name}}
      </mat-option>
    </mat-autocomplete>
  </mat-form-field>
</form>
Pavan Jadda
  • 4,306
  • 9
  • 47
  • 79
  • 1
    Your StackBlitz saved me, this a problem I tried to solve for 8-10 hours!! You're my hero of the week :) – Itay May 06 '21 at 21:05
  • 1
    @Itay I am glad it helped you. Still don't know why such basic feature is not supported in official material components – Pavan Jadda May 06 '21 at 23:36
  • BTW, if I delete the ```evt.stopPropagation();``` and put the ```focus()``` and ```openPane()``` in a ```setTimout``` with zero seconds it also works.. it's interesting. – Itay May 08 '21 at 20:29
  • And ```requestAnimationFrame``` instead of ```setTimeout()``` will also do the same :) – Itay May 08 '21 at 21:55
  • 1
    @Itay Since I need to use this in multiple projects, I created new library for this. You can see it here https://www.npmjs.com/package/@ngxsmart/autocomplete – Pavan Jadda May 27 '21 at 16:23
0

Call the filtered function after the date is received. IF the data is local then call filter function after the date is declared and if the data is coming from Rest api then exactly after success response call the filter function Like this

private getAllCategories() {
this.categoryService.getCategory("").subscribe(
     (response) => {
         if (response) {
             this.categories = response['rows'];


            //Now callling category filter after data is received

            this.filteredCategories = this.category.valueChanges
            .pipe(
            startWith(''),
            map(state => state ? this._filterCateg(state) : this.categories?.slice())
            );
         }
     },
     (error) => {
         console.info('error:', error);
             }
 );
}

It worked for me!

Zia Khan
  • 188
  • 2
  • 9