Skip to content

Commit 7fc38b9

Browse files
crisbetotinayuangao
authored andcommitted
fix(select): selected option not being highlighted when options are added asynchronously (#2499)
* fix(select): selected option not being highlighted when options are added asynchronously Fixes the select component not highlighting the model value when the options get added after initialization. Fixes #2497. * Address the feedback. * Fix linter errors.
1 parent 6f94aa1 commit 7fc38b9

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

src/lib/select/select.spec.ts

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,14 @@ describe('MdSelect', () => {
1616
beforeEach(async(() => {
1717
TestBed.configureTestingModule({
1818
imports: [MdSelectModule.forRoot(), ReactiveFormsModule, FormsModule],
19-
declarations: [BasicSelect, NgModelSelect, ManySelects, NgIfSelect, SelectWithChangeEvent],
19+
declarations: [
20+
BasicSelect,
21+
NgModelSelect,
22+
ManySelects,
23+
NgIfSelect,
24+
SelectInitWithoutOptions,
25+
SelectWithChangeEvent
26+
],
2027
providers: [
2128
{provide: OverlayContainer, useFactory: () => {
2229
overlayContainerElement = document.createElement('div') as HTMLElement;
@@ -239,6 +246,27 @@ describe('MdSelect', () => {
239246

240247
});
241248

249+
it('should select the proper option when the list of options is initialized at a later point',
250+
async(() => {
251+
let fixture = TestBed.createComponent(SelectInitWithoutOptions);
252+
let instance = fixture.componentInstance;
253+
254+
fixture.detectChanges();
255+
256+
// Wait for the initial writeValue promise.
257+
fixture.whenStable().then(() => {
258+
expect(instance.select.selected).toBeFalsy();
259+
260+
instance.addOptions();
261+
fixture.detectChanges();
262+
263+
// Wait for the next writeValue promise.
264+
fixture.whenStable().then(() => {
265+
expect(instance.select.selected).toBe(instance.options.toArray()[1]);
266+
});
267+
});
268+
}));
269+
242270
describe('forms integration', () => {
243271
let fixture: ComponentFixture<BasicSelect>;
244272
let trigger: HTMLElement;
@@ -1267,7 +1295,6 @@ class ManySelects {}
12671295
</md-select>
12681296
</div>
12691297
`,
1270-
12711298
})
12721299
class NgIfSelect {
12731300
isShowing = false;
@@ -1304,6 +1331,32 @@ class SelectWithChangeEvent {
13041331
changeListener = jasmine.createSpy('MdSelect change listener');
13051332
}
13061333

1334+
@Component({
1335+
selector: 'select-init-without-options',
1336+
template: `
1337+
<md-select placeholder="Food I want to eat right now" [formControl]="control">
1338+
<md-option *ngFor="let food of foods" [value]="food.value">
1339+
{{ food.viewValue }}
1340+
</md-option>
1341+
</md-select>
1342+
`
1343+
})
1344+
class SelectInitWithoutOptions {
1345+
foods: any[];
1346+
control = new FormControl('pizza-1');
1347+
1348+
@ViewChild(MdSelect) select: MdSelect;
1349+
@ViewChildren(MdOption) options: QueryList<MdOption>;
1350+
1351+
addOptions() {
1352+
this.foods = [
1353+
{ value: 'steak-0', viewValue: 'Steak' },
1354+
{ value: 'pizza-1', viewValue: 'Pizza' },
1355+
{ value: 'tacos-2', viewValue: 'Tacos'}
1356+
];
1357+
}
1358+
}
1359+
13071360
/**
13081361
* TODO: Move this to core testing utility until Angular has event faking
13091362
* support.

src/lib/select/select.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,15 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
241241
ngAfterContentInit() {
242242
this._initKeyManager();
243243
this._resetOptions();
244-
this._changeSubscription = this.options.changes.subscribe(() => this._resetOptions());
244+
this._changeSubscription = this.options.changes.subscribe(() => {
245+
this._resetOptions();
246+
247+
if (this._control) {
248+
// Defer setting the value in order to avoid the "Expression
249+
// has changed after it was checked" errors from Angular.
250+
Promise.resolve(null).then(() => this._setSelectionByValue(this._control.value));
251+
}
252+
});
245253
}
246254

247255
ngOnDestroy() {

0 commit comments

Comments
 (0)