fix(list): selection list not marking options as selected correctly when setting value with duplicates (#13363)

Along the same lines as #13361. Fixes the selection list not marking all selected options correctly when an array with duplicate values is assigned programmatically.
This commit is contained in:
Kristiyan Kostadinov
2018-10-03 20:13:32 +02:00
committed by vivian-hu
parent 56f2e50273
commit bef9a17c62
2 changed files with 32 additions and 12 deletions
+17 -5
View File
@@ -789,7 +789,7 @@ describe('MatSelectionList with forms', () => {
expect(fixture.componentInstance.selectedOptions).toEqual(['opt2', 'opt3']);
fixture.componentInstance.renderLastOption = false;
fixture.componentInstance.options.pop();
fixture.detectChanges();
tick();
@@ -829,6 +829,20 @@ describe('MatSelectionList with forms', () => {
expect(fixture.componentInstance.modelChangeSpy).not.toHaveBeenCalled();
});
it('should be able to programmatically set an array with duplicate values', fakeAsync(() => {
fixture.componentInstance.options = ['one', 'two', 'two', 'two', 'three'];
fixture.detectChanges();
tick();
listOptions = fixture.debugElement.queryAll(By.directive(MatListOption))
.map(optionDebugEl => optionDebugEl.componentInstance);
fixture.componentInstance.selectedOptions = ['one', 'two', 'two'];
fixture.detectChanges();
tick();
expect(listOptions.map(option => option.selected)).toEqual([true, true, true, false, false]);
}));
});
@@ -1076,15 +1090,13 @@ class SelectionListWithTabindexBinding {
@Component({
template: `
<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-list-option *ngFor="let option of options" [value]="option">{{option}}</mat-list-option>
</mat-selection-list>`
})
class SelectionListWithModel {
modelChangeSpy = jasmine.createSpy('model change spy');
selectedOptions: string[] = [];
renderLastOption = true;
options = ['opt1', 'opt2', 'opt3'];
}
@Component({
+15 -7
View File
@@ -473,13 +473,21 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
private _setOptionsFromValues(values: string[]) {
this.options.forEach(option => option._setSelected(false));
values
.map(value => {
return this.options.find(option =>
this.compareWith ? this.compareWith(option.value, value) : option.value === value);
})
.filter(Boolean)
.forEach(option => option!._setSelected(true));
values.forEach(value => {
const correspondingOption = this.options.find(option => {
// Skip options that are already in the model. This allows us to handle cases
// where the same primitive value is selected multiple times.
if (option.selected) {
return false;
}
return this.compareWith ? this.compareWith(option.value, value) : option.value === value;
});
if (correspondingOption) {
correspondingOption._setSelected(true);
}
});
}
/** Returns the values of the selected options. */