Issue
is there a way to change the selection of an HTML <select>
inside its own change event handler?
I have this code, which works perfectly fine. When I select an item in the drop down and then click the button, the item is removed from the drop down, added to the other array and the selection of the <select>
is reset to the null
element, which shows as -- Please select filter --
on the page.
<select class="form-select form-select-sm" [(ngModel)]="selectedFilter">
<option [ngValue]="null" [disabled]="true">-- Please select filter --</option>
<option *ngFor="let flt of availableFilters; let idx = index" [ngValue]="flt">{{ flt.caption }}</option>
</select>
<button class="btn btn-sm btn-primary" (click)="addFilter()" [disabled]="!selectedFilter"><i class="fa fa-plus"></i></button>
selectedFilter: AvailableFilter | null;
// [snip]
addFilter(): void {
if (this.selectedFilter) {
this.addFilterInternal(this.selectedFilter);
}
}
private addFilterInternal(flt: AvailableFilter): void {
// Add filter to active filters
this.activeFilters.push(flt);
// Remove filter from available filters
let idx = this.availableFilters.indexOf(flt);
this.availableFilters.splice(idx, 1);
// Reset filter selection drop-down
this.selectedFilter = null;
}
// [snap]
My users wanted this to be changed in a way that the action, the button triggers, should be executed on selection. So I added a change
listener to the <select>
that calls the exact same function of the component.
<select class="form-select form-select-sm" [(ngModel)]="selectedFilter" (change)="addFilter()">
<option [ngValue]="null" [disabled]="true">-- Please select filter --</option>
<option *ngFor="let flt of availableFilters; let idx = index" [ngValue]="flt">{{ flt.caption }}</option>
</select>
<button class="btn btn-sm btn-primary" (click)="addFilter()" [disabled]="!selectedFilter"><i class="fa fa-plus"></i></button>
But this does not work as expected. The element is still removed from the drop down and added to the other array, but the <select>
does not reset to the null
element. My guess is that this does not work because I am inside the change listener scope.
So I tried to encapsulate the this.selectedFilter = null
code inside a subscription on a Subject
, so it is executed asynchronously when the function ends (of course the function calls next()
and complete()
on the Subject after it moved the item between arrays). But this did not help, the behavior the the drop down stays the same.
Solution
As @MaxTuzenko suggested in the comments, I wrapped the this.selectedFilter = null
call in a setTimeout()
with a delay of 0. This did the trick and it works now as requested.
So the TypeScript code above changes to this, see the last two lines of addFilterInternal()
function.
selectedFilter: AvailableFilter | null;
// [snip]
addFilter(): void {
if (this.selectedFilter) {
this.addFilterInternal(this.selectedFilter);
}
}
private addFilterInternal(flt: AvailableFilter): void {
// Add filter to active filters
this.activeFilters.push(flt);
// Remove filter from available filters
let idx = this.availableFilters.indexOf(flt);
this.availableFilters.splice(idx, 1);
// Reset filter selection drop-down
const self = this;
setTimeout(() => self.selectedFilter = null, 0);
}
// [snap]
Answered By - marandus
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.