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.
This commit is contained in:
Kristiyan Kostadinov
2017-01-13 23:55:41 +01:00
committed by tinayuangao
parent 6f94aa1140
commit 7fc38b9bdd
2 changed files with 64 additions and 3 deletions
+55 -2
View File
@@ -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;
@@ -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;
@@ -1267,7 +1295,6 @@ class ManySelects {}
</md-select>
</div>
`,
})
class NgIfSelect {
isShowing = false;
@@ -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.
+9 -1
View File
@@ -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() {