Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular7 Mat-select intercept change

In my use case scenario I have a dropdown box (mat-select) which fills several input fields. Any change will fill the fields differently. Since the user could change a field I want to ask the user before the final change is executed if (s)he agree to clear(or change) all fields. In case of a NO the selection change will not happen and all fields should remain.

I tried to reduce the use case to a sample. I can select an item from the dropdown and do some further actions.

  <mat-select (selectionChange)="intercept($event.value)">
    <mat-option *ngFor="let food of foods" [value]="food.value" >
      {{food.viewValue}}
    </mat-option>
  </mat-select>

But at the time the selectionchange is exectued the content of the dropdown is already changed. For the sample I would like to have e.g.

  1. Select e.g. Pizza
  2. Popup appears
  3. !The dropdown remains on the original selection and after the popup disappears a change happen!
  4. Select e.g. Tacos
  5. Popup appears
  6. !The dropdown remains on the original selection (=Tacos) and after the popup disappears a change happen!

I have no clue how to intercept the change event before the change happen.

like image 505
LeO Avatar asked May 09 '26 22:05

LeO


1 Answers

We can't intercept the select change event before the change happens, because the selectionChange event is :

Event emitted when the selected value has been changed by the user.

, as described in Angular Material docs.

But we can trigger the update of the other form controls only after the user confirms it.

And, as @liqSTAR described, we must save the previous value of the selection and reset the select to it if the user cancels the popup.

A simple example would be:

<mat-select [(ngModel)]="selectedFood" (selectionChange)="intercept($event.value)">
selectedFood = '';
previousSelectedFood = '';


intercept(food:any) {
  const bottomSheetRef = this.bottomSheet.open(BottomSheetOverviewExampleSheet);

  bottomSheetRef.afterDismissed().subscribe( result => {
    if (result === true) {
       // update the the previous selected value
       this.previousSelectedFood = food;

       // update the other inputs based on `food` value
       this.otherInputValues = food;

    } else {
       // reset the selection to the previous value
       this.selectedFood = this.previousSelectedFood;
    }
  });
}

Demo: https://stackblitz.com/edit/angular-dhgfmx-9rzt7v

Now, the example above has an issue:

  • in UI, the select displays the new selected value, when the popup is opened, even if the user has not made a decision :

enter image description here

In order to fix this issue, we have to reset the selected value to its previous value immediately after the selectionChange event fires, that let the user decide, and if it confirms the selectios, we'll update update the select accordingly.

The code would be:

intercept(food:any) {

  // at first, reset the select to the previous value
  // so that the user could not see that the select has really changed
  // we need a timeout to make in work
  setTimeout( () => {
    this.selectedFood = this.previousSelectedFood;
  }, 1);

  const bottomSheetRef = this.bottomSheet.open(BottomSheetOverviewExampleSheet);

  bottomSheetRef.afterDismissed().subscribe( result => {
    if (result === true) {
       // update the selected value
       this.selectedFood = food;

       // update the previous selected value
       this.previousSelectedFood = food;

       // update the other inputs based on `food` value
       this.otherInputValues = food;
    }
  });
}

Demo: https://stackblitz.com/edit/angular-dhgfmx-xmvfvf

like image 63
andreivictor Avatar answered May 12 '26 13:05

andreivictor