Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Angular, onSelectionChange is not getting invoked for angular mat-option

I have a mat-form-field which contains an input and a mat-autocomplete that contains a mat-option. The input has (blur) event while the mat-option has (onSelectionChange) event.

The problem I have is that when I select an item, the blur is invoked before the onSelectionChange event of the mat-option. The method for the blur event empties the input in case the value doesn't exist in the drop down. In case I remove the (blur) event of the input then (onSelectionChange) gets invoked. I need this to get invoked before the (blur) event.

After some research I found that I can use .setTimeOut inside the function for the (blur) which allows its body to be invoked after the function for (onSelectionChange), however, with this fix, focusing away from the input will delay emptying the input if it has a wrong value.

Here is the html code I have:

<mat-form-field [style.width.%]="fieldWidthPercentage">
    <input matInput #tagsInput (blur)="checkIfMatch()">
    <mat-autocomplete #auto="matAutocomplete">
      <mat-option *ngFor="let item of filteredAutoCompleteItems | async" 
      (onSelectionChange)="selected(item)" [value]="item">
      {{ item.name }}
    </mat-option>
    </mat-autocomplete>
</mat-form-field>

here is the function for the (blur) event:

checkIfMatch() {
    setTimeout(() => {
    // . . .
    }, 1000);
  }
}
like image 209
Wael Avatar asked Oct 22 '18 19:10

Wael


2 Answers

You should use (optionSelected) on the <mat-autocomplete>.

<input matInput #tagsInput (blur)="checkIfMatch()">
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="selected($event.option.value)">
  <mat-option *ngFor="let item of filteredAutoCompleteItems | async" 
    [value]="item">
    {{ item.name }}
  </mat-option>
</mat-autocomplete>

Docs: https://material.angular.io/components/autocomplete/api#MatAutocompleteSelectedEvent

Example: Mat-autocomplete - How to access selected option?

like image 67
theblindprophet Avatar answered Sep 24 '22 13:09

theblindprophet


I found the solution to my question: For the call to blur, I added a check to see if the related target for the event is coming from the mat-option, in this case the code for checkIfMatch will not be invoked:

checkIfMatch(event) {

    if (event.relatedTarget && event.relatedTarget.id.indexOf('mat-option') > -1) {
      // In case of a direct selection, there is no need to check if it matches.
      event.preventDefault();
      return;
    }
...
}
like image 32
Wael Avatar answered Sep 24 '22 13:09

Wael