Skip to content

Commit f3120bf

Browse files
committed
fix(select): emitting change event twice for reset values
Fixes `mat-select` emitting its change event twice when a reset value is selected, as well as when it's selected twice in a row. This PR covers #10859 which would've introduced another issue. Fixes #10675. Fixes #13579.
1 parent 28e19a7 commit f3120bf

File tree

2 files changed

+62
-1
lines changed

2 files changed

+62
-1
lines changed

src/lib/select/select.spec.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2858,6 +2858,64 @@ describe('MatSelect', () => {
28582858
expect(spy).toHaveBeenCalledWith('steak-0');
28592859
}));
28602860

2861+
it('should emit once when a reset value is selected', fakeAsync(() => {
2862+
const fixture = TestBed.createComponent(BasicSelectWithoutForms);
2863+
const instance = fixture.componentInstance;
2864+
const spy = jasmine.createSpy('change spy');
2865+
2866+
instance.selectedFood = 'sandwich-2';
2867+
instance.foods[0].value = null;
2868+
fixture.detectChanges();
2869+
2870+
const subscription = instance.select.selectionChange.subscribe(spy);
2871+
2872+
fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement.click();
2873+
fixture.detectChanges();
2874+
flush();
2875+
2876+
(overlayContainerElement.querySelector('mat-option') as HTMLElement).click();
2877+
fixture.detectChanges();
2878+
flush();
2879+
2880+
expect(spy).toHaveBeenCalledTimes(1);
2881+
2882+
subscription.unsubscribe();
2883+
}));
2884+
2885+
it('should not emit the change event multiple times when a reset option is ' +
2886+
'selected twice in a row', fakeAsync(() => {
2887+
const fixture = TestBed.createComponent(BasicSelectWithoutForms);
2888+
const instance = fixture.componentInstance;
2889+
const spy = jasmine.createSpy('change spy');
2890+
2891+
instance.foods[0].value = null;
2892+
fixture.detectChanges();
2893+
2894+
const subscription = instance.select.selectionChange.subscribe(spy);
2895+
2896+
fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement.click();
2897+
fixture.detectChanges();
2898+
flush();
2899+
2900+
(overlayContainerElement.querySelector('mat-option') as HTMLElement).click();
2901+
fixture.detectChanges();
2902+
flush();
2903+
2904+
expect(spy).not.toHaveBeenCalled();
2905+
2906+
fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement.click();
2907+
fixture.detectChanges();
2908+
flush();
2909+
2910+
(overlayContainerElement.querySelector('mat-option') as HTMLElement).click();
2911+
fixture.detectChanges();
2912+
flush();
2913+
2914+
expect(spy).not.toHaveBeenCalled();
2915+
2916+
subscription.unsubscribe();
2917+
}));
2918+
28612919
});
28622920

28632921
describe('with option centering disabled', () => {

src/lib/select/select.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,10 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
914914
if (option.value == null && !this._multiple) {
915915
option.deselect();
916916
this._selectionModel.clear();
917-
this._propagateChanges(option.value);
917+
918+
if (this.value != null) {
919+
this._propagateChanges(option.value);
920+
}
918921
} else {
919922
option.selected ? this._selectionModel.select(option) : this._selectionModel.deselect(option);
920923

0 commit comments

Comments
 (0)