Skip to content

Commit 5a1c098

Browse files
committed
fix(overlay): emit attach and detach at appropriate times
* Emits the `attachments` when everything has been attached. * Emits the `detachments` when everything has been detached. * Completes the `attachments` observable before the `detachments`. Fixes #4871.
1 parent 12d6e96 commit 5a1c098

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

src/lib/core/overlay/overlay-ref.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ export class OverlayRef implements PortalHost {
4343
this.updateSize();
4444
this.updateDirection();
4545
this.updatePosition();
46-
this._attachments.next();
4746
this._state.scrollStrategy.enable();
4847

4948
// Enable pointer events for the overlay pane element.
@@ -53,6 +52,8 @@ export class OverlayRef implements PortalHost {
5352
this._attachBackdrop();
5453
}
5554

55+
this._attachments.next();
56+
5657
return attachResult;
5758
}
5859

@@ -68,9 +69,12 @@ export class OverlayRef implements PortalHost {
6869
// pointer events therefore. Depends on the position strategy and the applied pane boundaries.
6970
this._togglePointerEvents(false);
7071
this._state.scrollStrategy.disable();
72+
73+
let detachmentResult = this._portalHost.detach();
74+
7175
this._detachments.next();
7276

73-
return this._portalHost.detach();
77+
return detachmentResult;
7478
}
7579

7680
/**
@@ -84,9 +88,9 @@ export class OverlayRef implements PortalHost {
8488
this.detachBackdrop();
8589
this._portalHost.dispose();
8690
this._state.scrollStrategy.disable();
91+
this._attachments.complete();
8792
this._detachments.next();
8893
this._detachments.complete();
89-
this._attachments.complete();
9094
}
9195

9296
/**

src/lib/core/overlay/overlay.spec.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,24 @@ describe('Overlay', () => {
147147
expect(spy).toHaveBeenCalled();
148148
});
149149

150+
it('should emit the attachment event after everything is added to the DOM', () => {
151+
let state = new OverlayState();
152+
153+
state.hasBackdrop = true;
154+
155+
let overlayRef = overlay.create(state);
156+
157+
overlayRef.attachments().subscribe(() => {
158+
expect(overlayContainerElement.querySelector('pizza'))
159+
.toBeTruthy('Expected the overlay to have been attached.');
160+
161+
expect(overlayContainerElement.querySelector('.cdk-overlay-backdrop'))
162+
.toBeTruthy('Expected the backdrop to have been attached.');
163+
});
164+
165+
overlayRef.attach(componentPortal);
166+
});
167+
150168
it('should emit when an overlay is detached', () => {
151169
let overlayRef = overlay.create();
152170
let spy = jasmine.createSpy('detachments spy');
@@ -158,6 +176,18 @@ describe('Overlay', () => {
158176
expect(spy).toHaveBeenCalled();
159177
});
160178

179+
it('should emit the detachment event after the overlay is removed from the DOM', () => {
180+
let overlayRef = overlay.create();
181+
182+
overlayRef.detachments().subscribe(() => {
183+
expect(overlayContainerElement.querySelector('pizza'))
184+
.toBeFalsy('Expected the overlay to have been detached.');
185+
});
186+
187+
overlayRef.attach(componentPortal);
188+
overlayRef.detach();
189+
});
190+
161191
it('should emit and complete the observables when an overlay is disposed', () => {
162192
let overlayRef = overlay.create();
163193
let disposeSpy = jasmine.createSpy('dispose spy');
@@ -175,6 +205,19 @@ describe('Overlay', () => {
175205
expect(detachCompleteSpy).toHaveBeenCalled();
176206
});
177207

208+
it('should complete the attachment observable before the detachment one', () => {
209+
let overlayRef = overlay.create();
210+
let callbackOrder = [];
211+
212+
overlayRef.attachments().subscribe(null, null, () => callbackOrder.push('attach'));
213+
overlayRef.detachments().subscribe(null, null, () => callbackOrder.push('detach'));
214+
215+
overlayRef.attach(componentPortal);
216+
overlayRef.dispose();
217+
218+
expect(callbackOrder).toEqual(['attach', 'detach']);
219+
});
220+
178221
describe('positioning', () => {
179222
let state: OverlayState;
180223

@@ -413,7 +456,10 @@ describe('OverlayContainer theming', () => {
413456
});
414457

415458
/** Simple component for testing ComponentPortal. */
416-
@Component({template: '<p>Pizza</p>'})
459+
@Component({
460+
selector: 'pizza',
461+
template: '<p>Pizza</p>'
462+
})
417463
class PizzaMsg { }
418464

419465

0 commit comments

Comments
 (0)