@@ -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,51 @@ 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+ 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+
62100 // TODO(jelbourn): inputs for size, scroll behavior, animation, etc.
63101
64102 constructor (
@@ -68,40 +106,93 @@ export class ConnectedOverlayDirective implements OnInit, OnDestroy {
68106 this . _templatePortal = new TemplatePortal ( templateRef , viewContainerRef ) ;
69107 }
70108
71- get overlayRef ( ) {
109+ get overlayRef ( ) : OverlayRef {
72110 return this . _overlayRef ;
73111 }
74112
75- /** TODO: internal */
76- ngOnInit ( ) {
77- this . _createOverlay ( ) ;
78- }
79-
80113 /** TODO: internal */
81114 ngOnDestroy ( ) {
82115 this . _destroyOverlay ( ) ;
83116 }
84117
85- /** Creates an overlay and attaches this directive's template to it. */
118+ /** Creates an overlay */
86119 private _createOverlay ( ) {
87120 if ( ! this . positions || ! this . positions . length ) {
88121 this . positions = defaultPositionList ;
89122 }
90123
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 {
91129 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+ }
100185 }
101186
102187 /** Destroys the overlay created by this directive. */
103188 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+ }
105196 }
106197}
107198
0 commit comments