问题
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.
- Select e.g. Pizza
- Popup appears
- !The dropdown remains on the original selection and after the popup disappears a change happen!
- Select e.g. Tacos
- Popup appears
- !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.
回答1:
Far as I know, you cant prevent this change. The only possibility is to save the old value of the selection and reset it to this value if the user cancels the modal/popup. I had the same problem a while ago.
Edit: Maybe this could help Thread
回答2:
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 :
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
回答3:
Here's what i do.
template:
<mat-select [ngModel]="something"
(ngModelChange)="changeSomething($event, ngModelControl)"
#ngModelControl="ngModel">
...
</mat-select>
code:
changeSomething(value: any, ngModelControl: NgModel) {
if (<<false for whatever reason>>) {
// reset mat-select
ngModelControl.control.setValue(this.something);
} else {
this.something = value;
}
}
来源:https://stackoverflow.com/questions/56269995/angular7-mat-select-intercept-change