Skip to content

Commit e8a6ea1

Browse files
crisbetovivian-hu-zz
authored andcommitted
fix(chips): selectionChange event firing when value has not changed (#13173)
Fixes the `selectionChange` event always firing for the setter, `select`, `deselect` and `selectViaInteraction`, even if the value hasn't changed. Also gets rid of some repetition around emitting the event.
1 parent 63f2ef4 commit e8a6ea1

File tree

2 files changed

+76
-32
lines changed

2 files changed

+76
-32
lines changed

src/lib/chips/chip.spec.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,55 @@ describe('Chips', () => {
150150
expect(event.defaultPrevented).toBe(true);
151151
});
152152

153+
it('should not dispatch `selectionChange` event when deselecting a non-selected chip', () => {
154+
chipInstance.deselect();
155+
156+
const spy = jasmine.createSpy('selectionChange spy');
157+
const subscription = chipInstance.selectionChange.subscribe(spy);
158+
159+
chipInstance.deselect();
160+
161+
expect(spy).not.toHaveBeenCalled();
162+
subscription.unsubscribe();
163+
});
164+
165+
it('should not dispatch `selectionChange` event when selecting a selected chip', () => {
166+
chipInstance.select();
167+
168+
const spy = jasmine.createSpy('selectionChange spy');
169+
const subscription = chipInstance.selectionChange.subscribe(spy);
170+
171+
chipInstance.select();
172+
173+
expect(spy).not.toHaveBeenCalled();
174+
subscription.unsubscribe();
175+
});
176+
177+
it('should not dispatch `selectionChange` event when selecting a selected chip via ' +
178+
'user interaction', () => {
179+
chipInstance.select();
180+
181+
const spy = jasmine.createSpy('selectionChange spy');
182+
const subscription = chipInstance.selectionChange.subscribe(spy);
183+
184+
chipInstance.selectViaInteraction();
185+
186+
expect(spy).not.toHaveBeenCalled();
187+
subscription.unsubscribe();
188+
});
189+
190+
it('should not dispatch `selectionChange` through setter if the value did not change', () => {
191+
chipInstance.selected = false;
192+
193+
const spy = jasmine.createSpy('selectionChange spy');
194+
const subscription = chipInstance.selectionChange.subscribe(spy);
195+
196+
chipInstance.selected = false;
197+
198+
expect(spy).not.toHaveBeenCalled();
199+
subscription.unsubscribe();
200+
});
201+
153202
});
154203

155204
describe('keyboard behavior', () => {

src/lib/chips/chip.ts

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,12 @@ export class MatChip extends _MatChipMixinBase implements FocusableOption, OnDes
159159
@Input()
160160
get selected(): boolean { return this._selected; }
161161
set selected(value: boolean) {
162-
this._selected = coerceBooleanProperty(value);
163-
this.selectionChange.emit({
164-
source: this,
165-
isUserInput: false,
166-
selected: value
167-
});
162+
const coercedValue = coerceBooleanProperty(value);
163+
164+
if (coercedValue !== this._selected) {
165+
this._selected = coercedValue;
166+
this._dispatchSelectionChange();
167+
}
168168
}
169169
protected _selected: boolean = false;
170170

@@ -262,45 +262,32 @@ export class MatChip extends _MatChipMixinBase implements FocusableOption, OnDes
262262

263263
/** Selects the chip. */
264264
select(): void {
265-
this._selected = true;
266-
this.selectionChange.emit({
267-
source: this,
268-
isUserInput: false,
269-
selected: true
270-
});
265+
if (!this._selected) {
266+
this._selected = true;
267+
this._dispatchSelectionChange();
268+
}
271269
}
272270

273271
/** Deselects the chip. */
274272
deselect(): void {
275-
this._selected = false;
276-
this.selectionChange.emit({
277-
source: this,
278-
isUserInput: false,
279-
selected: false
280-
});
273+
if (this._selected) {
274+
this._selected = false;
275+
this._dispatchSelectionChange();
276+
}
281277
}
282278

283279
/** Select this chip and emit selected event */
284280
selectViaInteraction(): void {
285-
this._selected = true;
286-
// Emit select event when selected changes.
287-
this.selectionChange.emit({
288-
source: this,
289-
isUserInput: true,
290-
selected: true
291-
});
281+
if (!this._selected) {
282+
this._selected = true;
283+
this._dispatchSelectionChange(true);
284+
}
292285
}
293286

294287
/** Toggles the current selected state of this chip. */
295288
toggleSelected(isUserInput: boolean = false): boolean {
296289
this._selected = !this.selected;
297-
298-
this.selectionChange.emit({
299-
source: this,
300-
isUserInput,
301-
selected: this._selected
302-
});
303-
290+
this._dispatchSelectionChange(isUserInput);
304291
return this.selected;
305292
}
306293

@@ -375,6 +362,14 @@ export class MatChip extends _MatChipMixinBase implements FocusableOption, OnDes
375362
});
376363
});
377364
}
365+
366+
private _dispatchSelectionChange(isUserInput = false) {
367+
this.selectionChange.emit({
368+
source: this,
369+
isUserInput,
370+
selected: this._selected
371+
});
372+
}
378373
}
379374

380375

0 commit comments

Comments
 (0)