Skip to content

Commit 776f885

Browse files
committed
fix(list): selection list not marking options as selected correctly when setting value with duplicates
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.
1 parent 04234f0 commit 776f885

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

src/lib/list/selection-list.spec.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ describe('MatSelectionList with forms', () => {
789789

790790
expect(fixture.componentInstance.selectedOptions).toEqual(['opt2', 'opt3']);
791791

792-
fixture.componentInstance.renderLastOption = false;
792+
fixture.componentInstance.options.pop();
793793
fixture.detectChanges();
794794
tick();
795795

@@ -829,6 +829,20 @@ describe('MatSelectionList with forms', () => {
829829
expect(fixture.componentInstance.modelChangeSpy).not.toHaveBeenCalled();
830830
});
831831

832+
it('should be able to programmatically set an array with duplicate values', fakeAsync(() => {
833+
fixture.componentInstance.options = ['one', 'two', 'two', 'two', 'three'];
834+
fixture.detectChanges();
835+
tick();
836+
837+
listOptions = fixture.debugElement.queryAll(By.directive(MatListOption))
838+
.map(optionDebugEl => optionDebugEl.componentInstance);
839+
840+
fixture.componentInstance.selectedOptions = ['one', 'two', 'two'];
841+
fixture.detectChanges();
842+
tick();
843+
844+
expect(listOptions.map(option => option.selected)).toEqual([true, true, true, false, false]);
845+
}));
832846

833847
});
834848

@@ -1076,15 +1090,13 @@ class SelectionListWithTabindexBinding {
10761090
@Component({
10771091
template: `
10781092
<mat-selection-list [(ngModel)]="selectedOptions" (ngModelChange)="modelChangeSpy()">
1079-
<mat-list-option value="opt1">Option 1</mat-list-option>
1080-
<mat-list-option value="opt2">Option 2</mat-list-option>
1081-
<mat-list-option value="opt3" *ngIf="renderLastOption">Option 3</mat-list-option>
1093+
<mat-list-option *ngFor="let option of options" [value]="option">{{option}}</mat-list-option>
10821094
</mat-selection-list>`
10831095
})
10841096
class SelectionListWithModel {
10851097
modelChangeSpy = jasmine.createSpy('model change spy');
10861098
selectedOptions: string[] = [];
1087-
renderLastOption = true;
1099+
options = ['opt1', 'opt2', 'opt3'];
10881100
}
10891101

10901102
@Component({

src/lib/list/selection-list.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -473,13 +473,19 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
473473
private _setOptionsFromValues(values: string[]) {
474474
this.options.forEach(option => option._setSelected(false));
475475

476-
values
477-
.map(value => {
478-
return this.options.find(option =>
479-
this.compareWith ? this.compareWith(option.value, value) : option.value === value);
480-
})
481-
.filter(Boolean)
482-
.forEach(option => option!._setSelected(true));
476+
values.forEach(value => {
477+
const correspondingOption = this.options.find(option => {
478+
if (option.selected) {
479+
return false;
480+
}
481+
482+
return this.compareWith ? this.compareWith(option.value, value) : option.value === value;
483+
});
484+
485+
if (correspondingOption) {
486+
correspondingOption._setSelected(true);
487+
}
488+
});
483489
}
484490

485491
/** Returns the values of the selected options. */

0 commit comments

Comments
 (0)