Skip to content

Commit 51a8079

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 4b82786 commit 51a8079

File tree

2 files changed

+62
-1
lines changed

2 files changed

+62
-1
lines changed

src/material/select/select.spec.ts

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

3028+
it('should emit once when a reset value is selected', fakeAsync(() => {
3029+
const fixture = TestBed.createComponent(BasicSelectWithoutForms);
3030+
const instance = fixture.componentInstance;
3031+
const spy = jasmine.createSpy('change spy');
3032+
3033+
instance.selectedFood = 'sandwich-2';
3034+
instance.foods[0].value = null;
3035+
fixture.detectChanges();
3036+
3037+
const subscription = instance.select.selectionChange.subscribe(spy);
3038+
3039+
fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement.click();
3040+
fixture.detectChanges();
3041+
flush();
3042+
3043+
(overlayContainerElement.querySelector('mat-option') as HTMLElement).click();
3044+
fixture.detectChanges();
3045+
flush();
3046+
3047+
expect(spy).toHaveBeenCalledTimes(1);
3048+
3049+
subscription.unsubscribe();
3050+
}));
3051+
3052+
it('should not emit the change event multiple times when a reset option is ' +
3053+
'selected twice in a row', fakeAsync(() => {
3054+
const fixture = TestBed.createComponent(BasicSelectWithoutForms);
3055+
const instance = fixture.componentInstance;
3056+
const spy = jasmine.createSpy('change spy');
3057+
3058+
instance.foods[0].value = null;
3059+
fixture.detectChanges();
3060+
3061+
const subscription = instance.select.selectionChange.subscribe(spy);
3062+
3063+
fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement.click();
3064+
fixture.detectChanges();
3065+
flush();
3066+
3067+
(overlayContainerElement.querySelector('mat-option') as HTMLElement).click();
3068+
fixture.detectChanges();
3069+
flush();
3070+
3071+
expect(spy).not.toHaveBeenCalled();
3072+
3073+
fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement.click();
3074+
fixture.detectChanges();
3075+
flush();
3076+
3077+
(overlayContainerElement.querySelector('mat-option') as HTMLElement).click();
3078+
fixture.detectChanges();
3079+
flush();
3080+
3081+
expect(spy).not.toHaveBeenCalled();
3082+
3083+
subscription.unsubscribe();
3084+
}));
3085+
30283086
});
30293087

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

src/material/select/select.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,10 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
950950
if (option.value == null && !this._multiple) {
951951
option.deselect();
952952
this._selectionModel.clear();
953-
this._propagateChanges(option.value);
953+
954+
if (this.value != null) {
955+
this._propagateChanges(option.value);
956+
}
954957
} else {
955958
option.selected ? this._selectionModel.select(option) : this._selectionModel.deselect(option);
956959

0 commit comments

Comments
 (0)