Skip to content

Commit

Permalink
fix(select): selected option not being highlighted when options are a…
Browse files Browse the repository at this point in the history
…dded 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.
  • Loading branch information
crisbeto authored and tinayuangao committed Jan 13, 2017
1 parent 6f94aa1 commit 7fc38b9
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 3 deletions.
57 changes: 55 additions & 2 deletions src/lib/select/select.spec.ts
Expand Up @@ -16,7 +16,14 @@ describe('MdSelect', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MdSelectModule.forRoot(), ReactiveFormsModule, FormsModule],
declarations: [BasicSelect, NgModelSelect, ManySelects, NgIfSelect, SelectWithChangeEvent],
declarations: [
BasicSelect,
NgModelSelect,
ManySelects,
NgIfSelect,
SelectInitWithoutOptions,
SelectWithChangeEvent
],
providers: [
{provide: OverlayContainer, useFactory: () => {
overlayContainerElement = document.createElement('div') as HTMLElement;
Expand Down Expand Up @@ -239,6 +246,27 @@ describe('MdSelect', () => {

});

it('should select the proper option when the list of options is initialized at a later point',
async(() => {
let fixture = TestBed.createComponent(SelectInitWithoutOptions);
let instance = fixture.componentInstance;

fixture.detectChanges();

// Wait for the initial writeValue promise.
fixture.whenStable().then(() => {
expect(instance.select.selected).toBeFalsy();

instance.addOptions();
fixture.detectChanges();

// Wait for the next writeValue promise.
fixture.whenStable().then(() => {
expect(instance.select.selected).toBe(instance.options.toArray()[1]);
});
});
}));

describe('forms integration', () => {
let fixture: ComponentFixture<BasicSelect>;
let trigger: HTMLElement;
Expand Down Expand Up @@ -1267,7 +1295,6 @@ class ManySelects {}
</md-select>
</div>
`,

})
class NgIfSelect {
isShowing = false;
Expand Down Expand Up @@ -1304,6 +1331,32 @@ class SelectWithChangeEvent {
changeListener = jasmine.createSpy('MdSelect change listener');
}

@Component({
selector: 'select-init-without-options',
template: `
<md-select placeholder="Food I want to eat right now" [formControl]="control">
<md-option *ngFor="let food of foods" [value]="food.value">
{{ food.viewValue }}
</md-option>
</md-select>
`
})
class SelectInitWithoutOptions {
foods: any[];
control = new FormControl('pizza-1');

@ViewChild(MdSelect) select: MdSelect;
@ViewChildren(MdOption) options: QueryList<MdOption>;

addOptions() {
this.foods = [
{ value: 'steak-0', viewValue: 'Steak' },
{ value: 'pizza-1', viewValue: 'Pizza' },
{ value: 'tacos-2', viewValue: 'Tacos'}
];
}
}

/**
* TODO: Move this to core testing utility until Angular has event faking
* support.
Expand Down
10 changes: 9 additions & 1 deletion src/lib/select/select.ts
Expand Up @@ -241,7 +241,15 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
ngAfterContentInit() {
this._initKeyManager();
this._resetOptions();
this._changeSubscription = this.options.changes.subscribe(() => this._resetOptions());
this._changeSubscription = this.options.changes.subscribe(() => {
this._resetOptions();

if (this._control) {
// Defer setting the value in order to avoid the "Expression
// has changed after it was checked" errors from Angular.
Promise.resolve(null).then(() => this._setSelectionByValue(this._control.value));
}
});
}

ngOnDestroy() {
Expand Down

0 comments on commit 7fc38b9

Please sign in to comment.