fix(select): exception if selected value is accessed on init (#3785)

Fixes an error that is thrown if something attempts to access the `selected` value of `md-select` too early. The issue comes from the fact that the underlying `SelectionModel` gets initialized too late in `ngAfterContentInit`.

Fixes #3750.
This commit is contained in:
Kristiyan Kostadinov
2017-03-29 23:32:10 +02:00
committed by tinayuangao
parent 4282917f0c
commit e82457c118
2 changed files with 23 additions and 3 deletions
+17 -1
View File
@@ -46,7 +46,8 @@ describe('MdSelect', () => {
ThrowsErrorOnInit,
BasicSelectOnPush,
BasicSelectOnPushPreselected,
SelectWithPlainTabindex
SelectWithPlainTabindex,
SelectEarlyAccessSibling
],
providers: [
{provide: OverlayContainer, useFactory: () => {
@@ -1337,6 +1338,12 @@ describe('MdSelect', () => {
}).toThrowError(new RegExp('Oh no!', 'g'));
}));
it('should not throw when trying to access the selected value on init', async(() => {
expect(() => {
TestBed.createComponent(SelectEarlyAccessSibling).detectChanges();
}).not.toThrow();
}));
});
describe('change event', () => {
@@ -1941,6 +1948,15 @@ class MultiSelect {
})
class SelectWithPlainTabindex { }
@Component({
selector: 'select-early-sibling-access',
template: `
<md-select #select="mdSelect"></md-select>
<div *ngIf="select.selected"></div>
`
})
class SelectEarlyAccessSibling { }
class FakeViewportRuler {
getViewportRect() {
+6 -2
View File
@@ -15,6 +15,7 @@ import {
ViewChild,
ChangeDetectorRef,
Attribute,
OnInit,
} from '@angular/core';
import {MdOption, MdOptionSelectionChange} from '../core/option/option';
import {ENTER, SPACE} from '../core/keyboard/keycodes';
@@ -119,7 +120,7 @@ export type MdSelectFloatPlaceholderType = 'always' | 'never' | 'auto';
],
exportAs: 'mdSelect',
})
export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestroy {
export class MdSelect implements AfterContentInit, OnDestroy, OnInit, ControlValueAccessor {
/** Whether or not the overlay panel is open. */
private _panelOpen = false;
@@ -311,8 +312,11 @@ export class MdSelect implements AfterContentInit, ControlValueAccessor, OnDestr
this._tabIndex = parseInt(tabIndex) || 0;
}
ngAfterContentInit() {
ngOnInit() {
this._selectionModel = new SelectionModel<MdOption>(this.multiple, null, false);
}
ngAfterContentInit() {
this._initKeyManager();
this._changeSubscription = this.options.changes.startWith(null).subscribe(() => {