Skip to content

Commit 47751b4

Browse files
committed
fix(select): not marking options as selected correctly when setting value with duplicates
Fixes `mat-select` not marking all of the options as selected, when an array with duplicate values is assigned programmatically. Fixes #13179.
1 parent 2adf629 commit 47751b4

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

src/material/select/select.spec.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4264,6 +4264,32 @@ describe('MatSelect', () => {
42644264
expect(testInstance.control.value).toEqual([]);
42654265
});
42664266

4267+
it('should be able to programmatically set an array with duplicate values', fakeAsync(() => {
4268+
testInstance.foods = [
4269+
{ value: 'steak-0', viewValue: 'Steak' },
4270+
{ value: 'pizza-1', viewValue: 'Pizza' },
4271+
{ value: 'pizza-1', viewValue: 'Pizza' },
4272+
{ value: 'pizza-1', viewValue: 'Pizza' },
4273+
{ value: 'pizza-1', viewValue: 'Pizza' },
4274+
{ value: 'pizza-1', viewValue: 'Pizza' },
4275+
];
4276+
fixture.detectChanges();
4277+
testInstance.control.setValue(['steak-0', 'pizza-1', 'pizza-1', 'pizza-1']);
4278+
fixture.detectChanges();
4279+
4280+
trigger.click();
4281+
fixture.detectChanges();
4282+
4283+
const optionNodes = Array.from(overlayContainerElement.querySelectorAll('mat-option'));
4284+
const optionInstances = testInstance.options.toArray();
4285+
4286+
expect(optionNodes.map(node => node.classList.contains('mat-selected')))
4287+
.toEqual([true, true, true, true, false, false]);
4288+
4289+
expect(optionInstances.map(instance => instance.selected))
4290+
.toEqual([true, true, true, true, false, false]);
4291+
}));
4292+
42674293
});
42684294
});
42694295

src/material/select/select.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,12 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
875875
*/
876876
private _selectValue(value: any): MatOption | undefined {
877877
const correspondingOption = this.options.find((option: MatOption) => {
878+
// Skip options that are already in the model. This allows us to handle cases
879+
// where the same primitive value is selected multiple times.
880+
if (this._selectionModel.isSelected(option)) {
881+
return false;
882+
}
883+
878884
try {
879885
// Treat null as a special reset value.
880886
return option.value != null && this._compareWith(option.value, value);

0 commit comments

Comments
 (0)