From e82457c118eb0685de666b77de7dfa0fec6d0662 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Wed, 29 Mar 2017 23:32:10 +0200 Subject: [PATCH] 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. --- src/lib/select/select.spec.ts | 18 +++++++++++++++++- src/lib/select/select.ts | 8 ++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/lib/select/select.spec.ts b/src/lib/select/select.spec.ts index 0350621ad0dd..ce39310ce301 100644 --- a/src/lib/select/select.spec.ts +++ b/src/lib/select/select.spec.ts @@ -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: ` + +
+ ` +}) +class SelectEarlyAccessSibling { } + class FakeViewportRuler { getViewportRect() { diff --git a/src/lib/select/select.ts b/src/lib/select/select.ts index 1ef4a0d28c1d..91b1b9a47558 100644 --- a/src/lib/select/select.ts +++ b/src/lib/select/select.ts @@ -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(this.multiple, null, false); + } + + ngAfterContentInit() { this._initKeyManager(); this._changeSubscription = this.options.changes.startWith(null).subscribe(() => {