fix(list): selection list always firing change event for selectAll and deselectAll (#11029)

This commit is contained in:
Kristiyan Kostadinov
2018-05-01 10:53:16 -04:00
committed by Joey Perrott
parent 385f96dc65
commit 54c0b001d3
2 changed files with 52 additions and 9 deletions
+26 -1
View File
@@ -751,6 +751,30 @@ describe('MatSelectionList with forms', () => {
expect(fixture.componentInstance.selectedOptions).toEqual(['opt1']);
}));
it('should not dispatch the model change event if nothing changed using selectAll', () => {
expect(fixture.componentInstance.modelChangeSpy).not.toHaveBeenCalled();
selectionListDebug.componentInstance.selectAll();
fixture.detectChanges();
expect(fixture.componentInstance.modelChangeSpy).toHaveBeenCalledTimes(1);
selectionListDebug.componentInstance.selectAll();
fixture.detectChanges();
expect(fixture.componentInstance.modelChangeSpy).toHaveBeenCalledTimes(1);
});
it('should not dispatch the model change event if nothing changed using selectAll', () => {
expect(fixture.componentInstance.modelChangeSpy).not.toHaveBeenCalled();
selectionListDebug.componentInstance.deselectAll();
fixture.detectChanges();
expect(fixture.componentInstance.modelChangeSpy).not.toHaveBeenCalled();
});
});
describe('and formControl', () => {
@@ -968,13 +992,14 @@ class SelectionListWithTabindexBinding {
@Component({
template: `
<mat-selection-list [(ngModel)]="selectedOptions">
<mat-selection-list [(ngModel)]="selectedOptions" (ngModelChange)="modelChangeSpy()">
<mat-list-option value="opt1">Option 1</mat-list-option>
<mat-list-option value="opt2">Option 2</mat-list-option>
<mat-list-option value="opt3" *ngIf="renderLastOption">Option 3</mat-list-option>
</mat-selection-list>`
})
class SelectionListWithModel {
modelChangeSpy = jasmine.createSpy('model change spy');
selectedOptions: string[] = [];
renderLastOption = true;
}
+26 -8
View File
@@ -221,10 +221,10 @@ export class MatListOption extends _MatListOptionMixinBase
return this._element.nativeElement;
}
/** Sets the selected state of the option. */
_setSelected(selected: boolean) {
/** Sets the selected state of the option. Returns whether the value has changed. */
_setSelected(selected: boolean): boolean {
if (selected === this._selected) {
return;
return false;
}
this._selected = selected;
@@ -236,6 +236,7 @@ export class MatListOption extends _MatListOptionMixinBase
}
this._changeDetector.markForCheck();
return true;
}
}
@@ -302,7 +303,6 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
constructor(private _element: ElementRef, @Attribute('tabindex') tabIndex: string) {
super();
this.tabIndex = parseInt(tabIndex) || 0;
}
@@ -346,14 +346,12 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
/** Selects all of the options. */
selectAll() {
this.options.forEach(option => option._setSelected(true));
this._reportValueChange();
this._setAllOptionsSelected(true);
}
/** Deselects all of the options. */
deselectAll() {
this.options.forEach(option => option._setSelected(false));
this._reportValueChange();
this._setAllOptionsSelected(false);
}
/** Sets the focused option of the selection-list. */
@@ -479,6 +477,26 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
}
}
/**
* Sets the selected state on all of the options
* and emits an event if anything changed.
*/
private _setAllOptionsSelected(isSelected: boolean) {
// Keep track of whether anything changed, because we only want to
// emit the changed event when something actually changed.
let hasChanged = false;
this.options.forEach(option => {
if (option._setSelected(isSelected)) {
hasChanged = true;
}
});
if (hasChanged) {
this._reportValueChange();
}
}
/**
* Utility to ensure all indexes are valid.
* @param index The index to be checked.