Skip to content

Commit

Permalink
fix(select): unable to preselect array value in single selection mode (
Browse files Browse the repository at this point in the history
…#7603)

Fixes not being able to preselect an array if a select is in single selection mode due to an assumption that an array value means that we're in mutliple selection mode.

Fixes #7584.
  • Loading branch information
crisbeto authored and andrewseguin committed Oct 9, 2017
1 parent c12e4b5 commit d55aa0c
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 11 deletions.
39 changes: 39 additions & 0 deletions src/lib/select/select.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ describe('MatSelect', () => {
SelectInsideFormGroup,
NgModelCompareWithSelect,
CustomErrorBehaviorSelect,
SingleSelectWithPreselectedArrayValues,
],
providers: [
{provide: OverlayContainer, useFactory: () => {
Expand Down Expand Up @@ -1010,6 +1011,19 @@ describe('MatSelect', () => {
});
});
}));

it('should be able to preselect an array value in single-selection mode', fakeAsync(() => {
const fixture = TestBed.createComponent(SingleSelectWithPreselectedArrayValues);
fixture.detectChanges();
tick();
fixture.detectChanges();

const trigger = fixture.debugElement.query(By.css('.mat-select-trigger')).nativeElement;

expect(trigger.textContent).toContain('Pizza');
expect(fixture.componentInstance.options.toArray()[1].selected).toBe(true);
}));

});

describe('misc forms', () => {
Expand Down Expand Up @@ -3872,3 +3886,28 @@ class CustomErrorBehaviorSelect {
];
errorStateMatcher: ErrorStateMatcher;
}


@Component({
template: `
<mat-form-field>
<mat-select placeholder="Food" [(ngModel)]="selectedFoods">
<mat-option *ngFor="let food of foods"
[value]="food.value">{{ food.viewValue }}
</mat-option>
</mat-select>
</mat-form-field>
`
})
class SingleSelectWithPreselectedArrayValues {
foods: any[] = [
{ value: ['steak-0', 'steak-1'], viewValue: 'Steak' },
{ value: ['pizza-1', 'pizza-2'], viewValue: 'Pizza' },
{ value: ['tacos-2', 'tacos-3'], viewValue: 'Tacos' },
];

selectedFoods = this.foods[1].value;

@ViewChild(MatSelect) select: MatSelect;
@ViewChildren(MatOption) options: QueryList<MatOption>;
}
21 changes: 10 additions & 11 deletions src/lib/select/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -700,18 +700,17 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
* found with the designated value, the select trigger is cleared.
*/
private _setSelectionByValue(value: any | any[], isUserInput = false): void {
const isArray = Array.isArray(value);

if (this.multiple && value && !isArray) {
throw getMatSelectNonArrayValueError();
}

this._clearSelection();
if (this.multiple && value) {
if (!Array.isArray(value)) {
throw getMatSelectNonArrayValueError();
}

if (isArray) {
this._clearSelection();
value.forEach((currentValue: any) => this._selectValue(currentValue, isUserInput));
this._sortValues();
} else {
this._clearSelection();

const correspondingOption = this._selectValue(value, isUserInput);

// Shift focus to the active item. Note that we shouldn't do this in multiple
Expand Down Expand Up @@ -844,10 +843,10 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
private _propagateChanges(fallbackValue?: any): void {
let valueToEmit: any = null;

if (Array.isArray(this.selected)) {
valueToEmit = this.selected.map(option => option.value);
if (this.multiple) {
valueToEmit = (this.selected as MatOption[]).map(option => option.value);
} else {
valueToEmit = this.selected ? this.selected.value : fallbackValue;
valueToEmit = this.selected ? (this.selected as MatOption).value : fallbackValue;
}

this._value = valueToEmit;
Expand Down

0 comments on commit d55aa0c

Please sign in to comment.