@@ -2,11 +2,12 @@ import {
22 NgModule ,
33 ModuleWithProviders ,
44 Directive ,
5+ EventEmitter ,
56 TemplateRef ,
67 ViewContainerRef ,
7- OnInit ,
88 Input ,
99 OnDestroy ,
10+ Output ,
1011 ElementRef
1112} from '@angular/core' ;
1213import { Overlay , OVERLAY_PROVIDERS } from './overlay' ;
@@ -15,7 +16,8 @@ import {TemplatePortal} from '../portal/portal';
1516import { OverlayState } from './overlay-state' ;
1617import { ConnectionPositionPair } from './position/connected-position' ;
1718import { PortalModule } from '../portal/portal-directives' ;
18-
19+ import { ConnectedPositionStrategy } from './position/connected-position-strategy' ;
20+ import { Subscription } from 'rxjs/Subscription' ;
1921
2022/** Default set of positions for the overlay. Follows the behavior of a dropdown. */
2123let defaultPositionList = [
@@ -50,15 +52,52 @@ export class OverlayOrigin {
5052 * Directive to facilitate declarative creation of an Overlay using a ConnectedPositionStrategy.
5153 */
5254@Directive ( {
53- selector : '[connected-overlay]'
55+ selector : '[connected-overlay]' ,
56+ exportAs : 'connectedOverlay'
5457} )
55- export class ConnectedOverlayDirective implements OnInit , OnDestroy {
58+ export class ConnectedOverlayDirective implements OnDestroy {
5659 private _overlayRef : OverlayRef ;
5760 private _templatePortal : TemplatePortal ;
61+ private _open = false ;
62+ private _hasBackdrop = false ;
63+ private _backdropSubscription : Subscription ;
5864
5965 @Input ( ) origin : OverlayOrigin ;
6066 @Input ( ) positions : ConnectionPositionPair [ ] ;
6167
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+ // TODO: move the boolean coercion logic to a shared function in core
84+ set hasBackdrop ( value : any ) {
85+ this . _hasBackdrop = value != null && `${ value } ` !== 'false' ;
86+ }
87+
88+ @Input ( )
89+ get open ( ) {
90+ return this . _open ;
91+ }
92+
93+ set open ( value : boolean ) {
94+ value ? this . _attachOverlay ( ) : this . _detachOverlay ( ) ;
95+ this . _open = value ;
96+ }
97+
98+ /** Event emitted when the backdrop is clicked. */
99+ @Output ( ) backdropClick : EventEmitter < null > = new EventEmitter ( ) ;
100+
62101 // TODO(jelbourn): inputs for size, scroll behavior, animation, etc.
63102
64103 constructor (
@@ -68,40 +107,93 @@ export class ConnectedOverlayDirective implements OnInit, OnDestroy {
68107 this . _templatePortal = new TemplatePortal ( templateRef , viewContainerRef ) ;
69108 }
70109
71- get overlayRef ( ) {
110+ get overlayRef ( ) : OverlayRef {
72111 return this . _overlayRef ;
73112 }
74113
75- /** TODO: internal */
76- ngOnInit ( ) {
77- this . _createOverlay ( ) ;
78- }
79-
80114 /** TODO: internal */
81115 ngOnDestroy ( ) {
82116 this . _destroyOverlay ( ) ;
83117 }
84118
85- /** Creates an overlay and attaches this directive's template to it. */
119+ /** Creates an overlay */
86120 private _createOverlay ( ) {
87121 if ( ! this . positions || ! this . positions . length ) {
88122 this . positions = defaultPositionList ;
89123 }
90124
125+ this . _overlayRef = this . _overlay . create ( this . _buildConfig ( ) ) ;
126+ }
127+
128+ /** Builds the overlay config based on the directive's inputs */
129+ private _buildConfig ( ) : OverlayState {
91130 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 ) ;
131+
132+ if ( this . width || this . width === 0 ) {
133+ overlayConfig . width = this . width ;
134+ }
135+
136+ if ( this . height || this . height === 0 ) {
137+ overlayConfig . height = this . height ;
138+ }
139+
140+ overlayConfig . hasBackdrop = this . hasBackdrop ;
141+
142+ if ( this . backdropClass ) {
143+ overlayConfig . backdropClass = this . backdropClass ;
144+ }
145+
146+ overlayConfig . positionStrategy = this . _getPosition ( ) ;
147+
148+ return overlayConfig ;
149+ }
150+
151+ /** Returns the position of the overlay to be set on the overlay config */
152+ private _getPosition ( ) : ConnectedPositionStrategy {
153+ return this . _overlay . position ( ) . connectedTo (
154+ this . origin . elementRef ,
155+ { originX : this . positions [ 0 ] . overlayX , originY : this . positions [ 0 ] . originY } ,
156+ { overlayX : this . positions [ 0 ] . overlayX , overlayY : this . positions [ 0 ] . overlayY } ) ;
157+ }
158+
159+ /** Attaches the overlay and subscribes to backdrop clicks if backdrop exists */
160+ private _attachOverlay ( ) {
161+ if ( ! this . _overlayRef ) {
162+ this . _createOverlay ( ) ;
163+ }
164+
165+ if ( ! this . _overlayRef . hasAttached ( ) ) {
166+ this . _overlayRef . attach ( this . _templatePortal ) ;
167+ }
168+
169+ if ( this . hasBackdrop ) {
170+ this . _backdropSubscription = this . _overlayRef . backdropClick ( ) . subscribe ( ( ) => {
171+ this . backdropClick . emit ( null ) ;
172+ } ) ;
173+ }
174+ }
175+
176+ /** Detaches the overlay and unsubscribes to backdrop clicks if backdrop exists */
177+ private _detachOverlay ( ) {
178+ if ( this . _overlayRef ) {
179+ this . _overlayRef . detach ( ) ;
180+ }
181+
182+ if ( this . _backdropSubscription ) {
183+ this . _backdropSubscription . unsubscribe ( ) ;
184+ this . _backdropSubscription = null ;
185+ }
100186 }
101187
102188 /** Destroys the overlay created by this directive. */
103189 private _destroyOverlay ( ) {
104- this . _overlayRef . dispose ( ) ;
190+ if ( this . _overlayRef ) {
191+ this . _overlayRef . dispose ( ) ;
192+ }
193+
194+ if ( this . _backdropSubscription ) {
195+ this . _backdropSubscription . unsubscribe ( ) ;
196+ }
105197 }
106198}
107199
0 commit comments