diff --git a/src/lib/core/overlay/overlay-directives.spec.ts b/src/lib/core/overlay/overlay-directives.spec.ts
index 7cb58b1ff26d..2daece1e33d4 100644
--- a/src/lib/core/overlay/overlay-directives.spec.ts
+++ b/src/lib/core/overlay/overlay-directives.spec.ts
@@ -1,7 +1,7 @@
-import {ComponentFixture, TestBed} from '@angular/core/testing';
+import {ComponentFixture, TestBed, async} from '@angular/core/testing';
import {Component, ViewChild} from '@angular/core';
import {By} from '@angular/platform-browser';
-import {ConnectedOverlayDirective, OverlayModule} from './overlay-directives';
+import {ConnectedOverlayDirective, OverlayModule, OverlayOrigin} from './overlay-directives';
import {OverlayContainer} from './overlay-container';
import {ConnectedPositionStrategy} from './position/connected-position-strategy';
import {ConnectedOverlayPositionChange} from './position/connected-position';
@@ -18,7 +18,7 @@ describe('Overlay directives', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [OverlayModule],
- declarations: [ConnectedOverlayDirectiveTest],
+ declarations: [ConnectedOverlayDirectiveTest, ConnectedOverlayPropertyInitOrder],
providers: [
{provide: OverlayContainer, useFactory: () => {
overlayContainerElement = document.createElement('div');
@@ -111,6 +111,21 @@ describe('Overlay directives', () => {
'Expected overlay to have been detached.');
});
+ it('should not depend on the order in which the `origin` and `open` are set', async(() => {
+ fixture.destroy();
+
+ const propOrderFixture = TestBed.createComponent(ConnectedOverlayPropertyInitOrder);
+ propOrderFixture.detectChanges();
+
+ const overlayDirective = propOrderFixture.componentInstance.connectedOverlayDirective;
+
+ expect(() => {
+ overlayDirective.open = true;
+ overlayDirective.origin = propOrderFixture.componentInstance.trigger;
+ propOrderFixture.detectChanges();
+ }).not.toThrow();
+ }));
+
describe('inputs', () => {
it('should set the width', () => {
@@ -310,3 +325,14 @@ class ConnectedOverlayDirectiveTest {
@ViewChild(ConnectedOverlayDirective) connectedOverlayDirective: ConnectedOverlayDirective;
}
+
+@Component({
+ template: `
+
+ Menu content`,
+})
+class ConnectedOverlayPropertyInitOrder {
+ @ViewChild(ConnectedOverlayDirective) connectedOverlayDirective: ConnectedOverlayDirective;
+ @ViewChild('trigger') trigger: OverlayOrigin;
+}
+
diff --git a/src/lib/core/overlay/overlay-directives.ts b/src/lib/core/overlay/overlay-directives.ts
index b3ab073e02e6..aefd5c200795 100644
--- a/src/lib/core/overlay/overlay-directives.ts
+++ b/src/lib/core/overlay/overlay-directives.ts
@@ -10,6 +10,8 @@ import {
Output,
ElementRef,
Renderer2,
+ OnChanges,
+ SimpleChanges,
} from '@angular/core';
import {Overlay, OVERLAY_PROVIDERS} from './overlay';
import {OverlayRef} from './overlay-ref';
@@ -63,10 +65,9 @@ export class OverlayOrigin {
selector: '[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]',
exportAs: 'cdkConnectedOverlay'
})
-export class ConnectedOverlayDirective implements OnDestroy {
+export class ConnectedOverlayDirective implements OnDestroy, OnChanges {
private _overlayRef: OverlayRef;
private _templatePortal: TemplatePortal;
- private _open = false;
private _hasBackdrop = false;
private _backdropSubscription: Subscription;
private _positionSubscription: Subscription;
@@ -125,6 +126,9 @@ export class ConnectedOverlayDirective implements OnDestroy {
/** Strategy to be used when handling scroll events while the overlay is open. */
@Input() scrollStrategy: ScrollStrategy = new RepositionScrollStrategy(this._scrollDispatcher);
+ /** Whether the overlay is open. */
+ @Input() open: boolean = false;
+
/** Whether or not the overlay should attach a backdrop. */
@Input()
get hasBackdrop() {
@@ -135,16 +139,6 @@ export class ConnectedOverlayDirective implements OnDestroy {
this._hasBackdrop = coerceBooleanProperty(value);
}
- @Input()
- get open() {
- return this._open;
- }
-
- set open(value: boolean) {
- value ? this._attachOverlay() : this._detachOverlay();
- this._open = value;
- }
-
/** Event emitted when the backdrop is clicked. */
@Output() backdropClick = new EventEmitter();
@@ -183,6 +177,12 @@ export class ConnectedOverlayDirective implements OnDestroy {
this._destroyOverlay();
}
+ ngOnChanges(changes: SimpleChanges) {
+ if (changes['open']) {
+ this.open ? this._attachOverlay() : this._detachOverlay();
+ }
+ }
+
/** Creates an overlay */
private _createOverlay() {
if (!this.positions || !this.positions.length) {