Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is onSelectionChange called twice?

I am using Angular Material Autocomplete as follows:

<mat-autocomplete #autocomplete="matAutocomplete" [displayWith]="displayFn" autoActiveFirstOption>
  <mat-option *ngFor="let option of filteredOptions$ | async" [value]="option" (onSelectionChange)="onSelectionChanged(option)" >
    {{displayFn(option)}}
  </mat-option>
</mat-autocomplete>    

This is the handler:

onSelectionChanged(option) {
  console.log('Selected ' + option.name);
}

For some reason onSelectionChanged() gets called twice. The second time with the old value! I don't get why. What is happenning here?

Selecting item 1 and then item 2 and then item 3 will print:

> Selected item 1
> Selected item 2
> Selected item 1  // The unwanted call with the old value
> Selected item 3
> Selected item 2  // The unwanted call with the old value
like image 809
Stefan Falk Avatar asked Oct 26 '18 13:10

Stefan Falk


3 Answers

material has optionSelected event you can use it

<mat-autocomplete #autocomplete="matAutocomplete" (optionSelected)="onSelectionChanged($event)" [displayWith]="displayFn" autoActiveFirstOption>
 <mat-option *ngFor="let option of filteredOptions$ | async" [value]="option" >
    {{displayFn(option)}}
 </mat-option>
</mat-autocomplete>  

and get your value that way

onSelectionChanged(event) {
   console.log(event.option.value);
}
like image 159
Fateh Mohamed Avatar answered Oct 22 '22 14:10

Fateh Mohamed


I was facing the same problem for a mat-option inside a mat-select and fixed this way:

Template

<mat-select>
 <mat-option (onSelectionChange)="handleMetaSignalChange(metaSignal.name,$event);" *ngFor="let metaSignal of metaSignals" [value]="metaSignal">
  {{ metaSignal.name }}
 </mat-option>
</mat-select>

Code

 handleMetaSignalChange(metaSignal: string, event: any) {
    if (event.isUserInput) {    // ignore on deselection of the previous option
      console.log('Meta Signal Changed to ' + metaSignal + event.isUserInput);
    }
 }
like image 24
DevLoverUmar Avatar answered Oct 22 '22 15:10

DevLoverUmar


If you need to get the whole OBJECT and use its children values in the component:

1- Send both object and $event from DOM to component.ts.

<!-- Printing out the country name and flag only -->

 <mat-autocomplete #auto="matAutocomplete">
   <mat-option 
      *ngFor="let country of filteredCountries$ | async" 
      [value]="country.name"
      (onSelectionChange)="getSelectedCountry(country, $event)">
      <img class="example-option-img" aria-hidden [src]="country.flag" height="25">
      <span>{{country.name}}</span>
   </mat-option>
 </mat-autocomplete>

2- Now update your values in the component.ts

getSelectedCountry(country: ICountry, event: any): void {
   if (event.isUserInput) {    // ignore on deselection of the previous option
     console.log("Selected country name: ", country.name);
     console.log("Selected country code: ", country.code);
     console.log("Selected country flag link: ", country.flag);
}

Note: ICountry is my country Interface which is not required to have.

like image 8
Reza Taba Avatar answered Oct 22 '22 16:10

Reza Taba