diff --git a/src/lib/list/selection-list.spec.ts b/src/lib/list/selection-list.spec.ts index 7d5419cc162..7657dedc10b 100644 --- a/src/lib/list/selection-list.spec.ts +++ b/src/lib/list/selection-list.spec.ts @@ -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: ` - Option 1 - Option 2 - Option 3 + {{option}} ` }) class SelectionListWithModel { modelChangeSpy = jasmine.createSpy('model change spy'); selectedOptions: string[] = []; - renderLastOption = true; + options = ['opt1', 'opt2', 'opt3']; } @Component({ diff --git a/src/lib/list/selection-list.ts b/src/lib/list/selection-list.ts index 23993ba42ce..e62c2c41e13 100644 --- a/src/lib/list/selection-list.ts +++ b/src/lib/list/selection-list.ts @@ -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. */