@@ -2,11 +2,12 @@ import {
2
2
NgModule ,
3
3
ModuleWithProviders ,
4
4
Directive ,
5
+ EventEmitter ,
5
6
TemplateRef ,
6
7
ViewContainerRef ,
7
- OnInit ,
8
8
Input ,
9
9
OnDestroy ,
10
+ Output ,
10
11
ElementRef
11
12
} from '@angular/core' ;
12
13
import { Overlay , OVERLAY_PROVIDERS } from './overlay' ;
@@ -15,7 +16,8 @@ import {TemplatePortal} from '../portal/portal';
15
16
import { OverlayState } from './overlay-state' ;
16
17
import { ConnectionPositionPair } from './position/connected-position' ;
17
18
import { PortalModule } from '../portal/portal-directives' ;
18
-
19
+ import { ConnectedPositionStrategy } from './position/connected-position-strategy' ;
20
+ import { Subscription } from 'rxjs/Subscription' ;
19
21
20
22
/** Default set of positions for the overlay. Follows the behavior of a dropdown. */
21
23
let defaultPositionList = [
@@ -50,15 +52,51 @@ export class OverlayOrigin {
50
52
* Directive to facilitate declarative creation of an Overlay using a ConnectedPositionStrategy.
51
53
*/
52
54
@Directive ( {
53
- selector : '[connected-overlay]'
55
+ selector : '[connected-overlay]' ,
56
+ exportAs : 'connectedOverlay'
54
57
} )
55
- export class ConnectedOverlayDirective implements OnInit , OnDestroy {
58
+ export class ConnectedOverlayDirective implements OnDestroy {
56
59
private _overlayRef : OverlayRef ;
57
60
private _templatePortal : TemplatePortal ;
61
+ private _open = false ;
62
+ private _hasBackdrop = false ;
63
+ private _backdropSubscription : Subscription ;
58
64
59
65
@Input ( ) origin : OverlayOrigin ;
60
66
@Input ( ) positions : ConnectionPositionPair [ ] ;
61
67
68
+ /** The width of the overlay panel. */
69
+ @Input ( ) width : number | string ;
70
+
71
+ /** The height of the overlay panel. */
72
+ @Input ( ) height : number | string ;
73
+
74
+ /** The custom class to be set on the backdrop element. */
75
+ @Input ( ) backdropClass : string ;
76
+
77
+ /** Whether or not the overlay should attach a backdrop. */
78
+ @Input ( )
79
+ get hasBackdrop ( ) {
80
+ return this . _hasBackdrop ;
81
+ }
82
+
83
+ set hasBackdrop ( value : any ) {
84
+ this . _hasBackdrop = value === '' || ( ! ! value && value !== 'false' ) ;
85
+ }
86
+
87
+ @Input ( )
88
+ get open ( ) {
89
+ return this . _open ;
90
+ }
91
+
92
+ set open ( value : boolean ) {
93
+ value ? this . _attachOverlay ( ) : this . _detachOverlay ( ) ;
94
+ this . _open = value ;
95
+ }
96
+
97
+ /** Event emitted when the backdrop is clicked. */
98
+ @Output ( ) backdropClick = new EventEmitter ( ) ;
99
+
62
100
// TODO(jelbourn): inputs for size, scroll behavior, animation, etc.
63
101
64
102
constructor (
@@ -68,40 +106,93 @@ export class ConnectedOverlayDirective implements OnInit, OnDestroy {
68
106
this . _templatePortal = new TemplatePortal ( templateRef , viewContainerRef ) ;
69
107
}
70
108
71
- get overlayRef ( ) {
109
+ get overlayRef ( ) : OverlayRef {
72
110
return this . _overlayRef ;
73
111
}
74
112
75
- /** TODO: internal */
76
- ngOnInit ( ) {
77
- this . _createOverlay ( ) ;
78
- }
79
-
80
113
/** TODO: internal */
81
114
ngOnDestroy ( ) {
82
115
this . _destroyOverlay ( ) ;
83
116
}
84
117
85
- /** Creates an overlay and attaches this directive's template to it. */
118
+ /** Creates an overlay */
86
119
private _createOverlay ( ) {
87
120
if ( ! this . positions || ! this . positions . length ) {
88
121
this . positions = defaultPositionList ;
89
122
}
90
123
124
+ this . _overlayRef = this . _overlay . create ( this . _buildConfig ( ) ) ;
125
+ }
126
+
127
+ /** Builds the overlay config based on the directive's inputs */
128
+ private _buildConfig ( ) : OverlayState {
91
129
let overlayConfig = new OverlayState ( ) ;
92
- overlayConfig . positionStrategy =
93
- this . _overlay . position ( ) . connectedTo (
94
- this . origin . elementRef ,
95
- { originX : this . positions [ 0 ] . overlayX , originY : this . positions [ 0 ] . originY } ,
96
- { overlayX : this . positions [ 0 ] . overlayX , overlayY : this . positions [ 0 ] . overlayY } ) ;
97
-
98
- this . _overlayRef = this . _overlay . create ( overlayConfig ) ;
99
- this . _overlayRef . attach ( this . _templatePortal ) ;
130
+
131
+ if ( this . width || this . width === 0 ) {
132
+ overlayConfig . width = this . width ;
133
+ }
134
+
135
+ if ( this . height || this . height === 0 ) {
136
+ overlayConfig . height = this . height ;
137
+ }
138
+
139
+ overlayConfig . hasBackdrop = this . hasBackdrop ;
140
+
141
+ if ( this . backdropClass ) {
142
+ overlayConfig . backdropClass = this . backdropClass ;
143
+ }
144
+
145
+ overlayConfig . positionStrategy = this . _getPosition ( ) ;
146
+
147
+ return overlayConfig ;
148
+ }
149
+
150
+ /** Returns the position of the overlay to be set on the overlay config */
151
+ private _getPosition ( ) : ConnectedPositionStrategy {
152
+ return this . _overlay . position ( ) . connectedTo (
153
+ this . origin . elementRef ,
154
+ { originX : this . positions [ 0 ] . overlayX , originY : this . positions [ 0 ] . originY } ,
155
+ { overlayX : this . positions [ 0 ] . overlayX , overlayY : this . positions [ 0 ] . overlayY } ) ;
156
+ }
157
+
158
+ /** Attaches the overlay and subscribes to backdrop clicks if backdrop exists */
159
+ private _attachOverlay ( ) {
160
+ if ( ! this . _overlayRef ) {
161
+ this . _createOverlay ( ) ;
162
+ }
163
+
164
+ if ( ! this . _overlayRef . hasAttached ( ) ) {
165
+ this . _overlayRef . attach ( this . _templatePortal ) ;
166
+ }
167
+
168
+ if ( this . hasBackdrop ) {
169
+ this . _backdropSubscription = this . _overlayRef . backdropClick ( ) . subscribe ( ( ) => {
170
+ this . backdropClick . emit ( ) ;
171
+ } ) ;
172
+ }
173
+ }
174
+
175
+ /** Detaches the overlay and unsubscribes to backdrop clicks if backdrop exists */
176
+ private _detachOverlay ( ) {
177
+ if ( this . _overlayRef ) {
178
+ this . _overlayRef . detach ( ) ;
179
+ }
180
+
181
+ if ( this . _backdropSubscription ) {
182
+ this . _backdropSubscription . unsubscribe ( ) ;
183
+ this . _backdropSubscription = null ;
184
+ }
100
185
}
101
186
102
187
/** Destroys the overlay created by this directive. */
103
188
private _destroyOverlay ( ) {
104
- this . _overlayRef . dispose ( ) ;
189
+ if ( this . _overlayRef ) {
190
+ this . _overlayRef . dispose ( ) ;
191
+ }
192
+
193
+ if ( this . _backdropSubscription ) {
194
+ this . _backdropSubscription . unsubscribe ( ) ;
195
+ }
105
196
}
106
197
}
107
198
0 commit comments