@@ -12,25 +12,28 @@ import {OverlayConfig} from './overlay-config';
12
12
import { OverlayKeyboardDispatcher } from './keyboard/overlay-keyboard-dispatcher' ;
13
13
import { Observable } from 'rxjs/Observable' ;
14
14
import { Subject } from 'rxjs/Subject' ;
15
+ import { MatBackdrop } from './backdrop' ;
16
+ import { ComponentPortal } from '@angular/cdk/portal' ;
15
17
import { take } from 'rxjs/operators/take' ;
16
-
18
+ import { empty } from 'rxjs/observable/empty' ;
17
19
18
20
/**
19
21
* Reference to an overlay that has been created with the Overlay service.
20
22
* Used to manipulate or dispose of said overlay.
21
23
*/
22
24
export class OverlayRef implements PortalOutlet {
23
- private _backdropElement : HTMLElement | null = null ;
24
25
private _backdropClick : Subject < any > = new Subject ( ) ;
25
26
private _attachments = new Subject < void > ( ) ;
26
27
private _detachments = new Subject < void > ( ) ;
28
+ private _backdropInstance : MatBackdrop | null ;
27
29
28
30
/** Stream of keydown events dispatched to this overlay. */
29
31
_keydownEvents = new Subject < KeyboardEvent > ( ) ;
30
32
31
33
constructor (
32
34
private _portalOutlet : PortalOutlet ,
33
35
private _pane : HTMLElement ,
36
+ private _backdropHost : PortalOutlet | null ,
34
37
private _config : OverlayConfig ,
35
38
private _ngZone : NgZone ,
36
39
private _keyboardDispatcher : OverlayKeyboardDispatcher ) {
@@ -51,7 +54,7 @@ export class OverlayRef implements PortalOutlet {
51
54
* @returns The portal attachment result.
52
55
*/
53
56
attach ( portal : Portal < any > ) : any {
54
- let attachResult = this . _portalOutlet . attach ( portal ) ;
57
+ const attachResult = this . _portalOutlet . attach ( portal ) ;
55
58
56
59
if ( this . _config . positionStrategy ) {
57
60
this . _config . positionStrategy . attach ( this ) ;
@@ -76,14 +79,15 @@ export class OverlayRef implements PortalOutlet {
76
79
// Enable pointer events for the overlay pane element.
77
80
this . _togglePointerEvents ( true ) ;
78
81
79
- if ( this . _config . hasBackdrop ) {
80
- this . _attachBackdrop ( ) ;
82
+ if ( this . _backdropHost ) {
83
+ this . _backdropInstance = this . _backdropHost . attach ( new ComponentPortal ( MatBackdrop ) ) . instance ;
84
+ this . _backdropInstance ! . _setClass ( this . _config . backdropClass ! ) ;
81
85
}
82
86
83
87
if ( this . _config . panelClass ) {
84
88
// We can't do a spread here, because IE doesn't support setting multiple classes.
85
89
if ( Array . isArray ( this . _config . panelClass ) ) {
86
- this . _config . panelClass . forEach ( cls => this . _pane . classList . add ( cls ) ) ;
90
+ this . _config . panelClass . forEach ( cssClass => this . _pane . classList . add ( cssClass ) ) ;
87
91
} else {
88
92
this . _pane . classList . add ( this . _config . panelClass ) ;
89
93
}
@@ -107,7 +111,9 @@ export class OverlayRef implements PortalOutlet {
107
111
return ;
108
112
}
109
113
110
- this . detachBackdrop ( ) ;
114
+ if ( this . _backdropHost && this . _backdropHost . hasAttached ( ) ) {
115
+ this . _backdropHost . detach ( ) ;
116
+ }
111
117
112
118
// When the overlay is detached, the pane element should disable pointer events.
113
119
// This is necessary because otherwise the pane element will cover the page and disable
@@ -147,7 +153,7 @@ export class OverlayRef implements PortalOutlet {
147
153
this . _config . scrollStrategy . disable ( ) ;
148
154
}
149
155
150
- this . detachBackdrop ( ) ;
156
+ this . disposeBackdrop ( ) ;
151
157
this . _keyboardDispatcher . remove ( this ) ;
152
158
this . _portalOutlet . dispose ( ) ;
153
159
this . _attachments . complete ( ) ;
@@ -172,7 +178,7 @@ export class OverlayRef implements PortalOutlet {
172
178
* Gets an observable that emits when the backdrop has been clicked.
173
179
*/
174
180
backdropClick ( ) : Observable < void > {
175
- return this . _backdropClick . asObservable ( ) ;
181
+ return this . _backdropInstance ? this . _backdropInstance . _clickStream : empty < void > ( ) ;
176
182
}
177
183
178
184
/** Gets an observable that emits when the overlay has been attached. */
@@ -241,31 +247,6 @@ export class OverlayRef implements PortalOutlet {
241
247
this . _pane . style . pointerEvents = enablePointer ? 'auto' : 'none' ;
242
248
}
243
249
244
- /** Attaches a backdrop for this overlay. */
245
- private _attachBackdrop ( ) {
246
- this . _backdropElement = document . createElement ( 'div' ) ;
247
- this . _backdropElement . classList . add ( 'cdk-overlay-backdrop' ) ;
248
-
249
- if ( this . _config . backdropClass ) {
250
- this . _backdropElement . classList . add ( this . _config . backdropClass ) ;
251
- }
252
-
253
- // Insert the backdrop before the pane in the DOM order,
254
- // in order to handle stacked overlays properly.
255
- this . _pane . parentElement ! . insertBefore ( this . _backdropElement , this . _pane ) ;
256
-
257
- // Forward backdrop clicks such that the consumer of the overlay can perform whatever
258
- // action desired when such a click occurs (usually closing the overlay).
259
- this . _backdropElement . addEventListener ( 'click' , ( ) => this . _backdropClick . next ( null ) ) ;
260
-
261
- // Add class to fade-in the backdrop after one frame.
262
- requestAnimationFrame ( ( ) => {
263
- if ( this . _backdropElement ) {
264
- this . _backdropElement . classList . add ( 'cdk-overlay-backdrop-showing' ) ;
265
- }
266
- } ) ;
267
- }
268
-
269
250
/**
270
251
* Updates the stacking order of the element, moving it to the top if necessary.
271
252
* This is required in cases where one overlay was detached, while another one,
@@ -279,45 +260,29 @@ export class OverlayRef implements PortalOutlet {
279
260
}
280
261
}
281
262
282
- /** Detaches the backdrop (if any) associated with the overlay. */
283
- detachBackdrop ( ) : void {
284
- let backdropToDetach = this . _backdropElement ;
285
-
286
- if ( backdropToDetach ) {
287
- let finishDetach = ( ) => {
288
- // It may not be attached to anything in certain cases (e.g. unit tests).
289
- if ( backdropToDetach && backdropToDetach . parentNode ) {
290
- backdropToDetach . parentNode . removeChild ( backdropToDetach ) ;
291
- }
292
-
293
- // It is possible that a new portal has been attached to this overlay since we started
294
- // removing the backdrop. If that is the case, only clear the backdrop reference if it
295
- // is still the same instance that we started to remove.
296
- if ( this . _backdropElement == backdropToDetach ) {
297
- this . _backdropElement = null ;
298
- }
299
- } ;
300
-
301
- backdropToDetach . classList . remove ( 'cdk-overlay-backdrop-showing' ) ;
302
-
303
- if ( this . _config . backdropClass ) {
304
- backdropToDetach . classList . remove ( this . _config . backdropClass ) ;
305
- }
306
-
307
- backdropToDetach . addEventListener ( 'transitionend' , finishDetach ) ;
263
+ /** Animates out and disposes of the backdrop. */
264
+ disposeBackdrop ( ) : void {
265
+ if ( this . _backdropHost ) {
266
+ if ( this . _backdropHost . hasAttached ( ) ) {
267
+ this . _backdropHost . detach ( ) ;
308
268
309
- // If the backdrop doesn't have a transition, the `transitionend` event won't fire.
310
- // In this case we make it unclickable and we try to remove it after a delay.
311
- backdropToDetach . style . pointerEvents = 'none' ;
312
-
313
- // Run this outside the Angular zone because there's nothing that Angular cares about.
314
- // If it were to run inside the Angular zone, every test that used Overlay would have to be
315
- // either async or fakeAsync.
316
- this . _ngZone . runOutsideAngular ( ( ) => {
317
- setTimeout ( finishDetach , 500 ) ;
318
- } ) ;
269
+ this . _backdropInstance ! . _animationStream . pipe ( take ( 1 ) ) . subscribe ( ( ) => {
270
+ this . _backdropHost ! . dispose ( ) ;
271
+ this . _backdropHost = this . _backdropInstance = null ;
272
+ } ) ;
273
+ } else {
274
+ this . _backdropHost . dispose ( ) ;
275
+ }
319
276
}
320
277
}
278
+
279
+ /**
280
+ * Detaches the backdrop (if any) associated with the overlay.
281
+ * @deprecated Use `disposeBackdrop` instead.
282
+ */
283
+ detachBackdrop ( ) : void {
284
+ this . disposeBackdrop ( ) ;
285
+ }
321
286
}
322
287
323
288
function formatCssUnit ( value : number | string ) {
0 commit comments