1
- import { Component , Renderer , ElementRef , HostListener , ViewEncapsulation } from '@angular/core' ;
1
+ import { Component , ViewChild , ViewContainerRef , DynamicComponentLoader } from '@angular/core' ;
2
+ import { Renderer , ElementRef } from '@angular/core' ;
2
3
3
4
import { Animation } from '../../animations/animation' ;
4
5
import { Transition , TransitionOptions } from '../../transitions/transition' ;
5
6
import { Config } from '../../config/config' ;
6
7
import { NavParams } from '../nav/nav-params' ;
8
+ import { Platform } from '../../platform/platform'
7
9
import { isPresent , isUndefined , isDefined } from '../../util/util' ;
8
10
import { ViewController } from '../nav/view-controller' ;
9
11
10
- const POPOVER_BODY_PADDING = 6 ;
12
+ const POPOVER_BODY_PADDING = 2 ;
11
13
12
14
/**
13
15
* @name Popover
@@ -16,14 +18,15 @@ const POPOVER_BODY_PADDING = 6;
16
18
*/
17
19
export class Popover extends ViewController {
18
20
19
- constructor ( opts : PopoverOptions = { } ) {
21
+ constructor ( componentType , data : any = { } , opts : PopoverOptions = { } ) {
20
22
opts . showBackdrop = isPresent ( opts . showBackdrop ) ? ! ! opts . showBackdrop : true ;
21
23
opts . enableBackdropDismiss = isPresent ( opts . enableBackdropDismiss ) ? ! ! opts . enableBackdropDismiss : true ;
22
24
23
- super ( PopoverCmp , opts ) ;
25
+ data . componentType = componentType ;
26
+ data . opts = opts ;
27
+ super ( PopoverCmp , data ) ;
24
28
this . viewType = 'popover' ;
25
29
this . isOverlay = true ;
26
- this . usePortal = false ;
27
30
28
31
// by default, popovers should not fire lifecycle events of other views
29
32
// for example, when a popover enters, the current active view should
@@ -44,16 +47,16 @@ export class Popover extends ViewController {
44
47
*
45
48
* | Option | Type | Description |
46
49
* |-----------------------|------------|------------------------------------------------------------------------------------------------------------------|
47
- * | template |`string` | The html content for the popover. |
48
50
* | cssClass |`string` | An additional class for custom styles. |
49
51
* | showBackdrop |`boolean` | Whether to show the backdrop. Default true. |
50
52
* | enableBackdropDismiss |`boolean` | Wheather the popover should be dismissed by tapping the backdrop. Default true. |
51
53
*
52
54
*
55
+ * @param {object } data Any data to pass to the popover view
53
56
* @param {object } opts Popover options
54
57
*/
55
- static create ( opts : PopoverOptions = { } ) {
56
- return new Popover ( opts ) ;
58
+ static create ( componentType , data = { } , opts : PopoverOptions = { } ) {
59
+ return new Popover ( componentType , data , opts ) ;
57
60
}
58
61
59
62
}
@@ -64,30 +67,29 @@ export class Popover extends ViewController {
64
67
@Component ( {
65
68
selector : 'ion-popover' ,
66
69
template :
67
- '<div disable-activated class="backdrop" (click)="bdClick()" [class.hide-backdrop]="!d.showBackdrop" role="presentation" ></div>' +
70
+ '<div disable-activated class="backdrop" (click)="bdClick()" [class.hide-backdrop]="!d.showBackdrop"></div>' +
68
71
'<div class="popover-arrow"></div>' +
69
72
'<div class="popover-wrapper">' +
70
- '<div *ngIf="d.template" [innerHTML]="d.template" class="popover-template"></div>' +
71
- '</div>' ,
72
- host : {
73
- 'role' : 'dialog'
74
- } ,
75
- encapsulation : ViewEncapsulation . None ,
73
+ '<div #viewport></div>' +
74
+ '</div>'
76
75
} )
77
76
class PopoverCmp {
77
+ @ViewChild ( 'viewport' , { read : ViewContainerRef } ) viewport : ViewContainerRef ;
78
+
78
79
private d : any ;
79
80
private id : number ;
80
81
private created : number ;
81
82
private showSpinner : boolean ;
82
83
83
- constructor (
84
- private _viewCtrl : ViewController ,
85
- private _config : Config ,
84
+ constructor ( private _loader : DynamicComponentLoader ,
86
85
private _elementRef : ElementRef ,
87
86
private _renderer : Renderer ,
88
- params : NavParams
87
+ private _config : Config ,
88
+ private _navParams : NavParams ,
89
+ private _viewCtrl : ViewController ,
90
+ private _platform : Platform
89
91
) {
90
- this . d = params . data ;
92
+ this . d = _navParams . data . opts ;
91
93
this . created = Date . now ( ) ;
92
94
93
95
if ( this . d . cssClass ) {
@@ -97,9 +99,18 @@ class PopoverCmp {
97
99
this . id = ( ++ popoverIds ) ;
98
100
}
99
101
102
+ onPageWillEnter ( ) {
103
+ this . _loader . loadNextToLocation ( this . _navParams . data . componentType , this . viewport ) . then ( componentRef => {
104
+ this . _viewCtrl . setInstance ( componentRef . instance ) ;
105
+
106
+ // manually fire onPageWillEnter() since ModalCmp's onPageWillEnter already happened
107
+ this . _viewCtrl . willEnter ( ) ;
108
+ } ) ;
109
+ }
110
+
100
111
ngOnInit ( ) {
101
- if ( this . d . element && this . d . event ) {
102
- this . positionView ( this . d . element , this . d . event ) ;
112
+ if ( this . d . event ) {
113
+ this . positionView ( this . d . event ) ;
103
114
}
104
115
}
105
116
@@ -110,71 +121,64 @@ class PopoverCmp {
110
121
}
111
122
}
112
123
113
- positionView ( targetEle , ev ) {
114
- let popoverEle = this . _elementRef . nativeElement ;
115
- let popoverWrapperEle = popoverEle . querySelector ( '.popover-wrapper' ) ;
124
+ positionView ( ev ) {
125
+ let nativeEle = this . _elementRef . nativeElement ;
116
126
117
- // Popover width and height
118
- let popoverWidth = popoverWrapperEle . offsetWidth ;
119
- let popoverHeight = popoverWrapperEle . offsetHeight ;
127
+ // Popover wrapper width and height
128
+ let popoverEle = nativeEle . querySelector ( '.popover-wrapper' ) ;
129
+ let popoverDim = popoverEle . getBoundingClientRect ( ) ;
130
+ let popoverWidth = popoverDim . width ;
131
+ let popoverHeight = popoverDim . height ;
120
132
121
133
// Window body width and height
122
- let bodyWidth = window . innerWidth ;
123
- let bodyHeight = window . innerHeight ;
124
-
125
- // Clicked element width and height
126
- targetEle = targetEle . _elementRef . nativeElement ;
127
- let targetWidth = targetEle . offsetWidth ;
128
- let targetHeight = targetEle . offsetHeight ;
134
+ let bodyWidth = this . _platform . width ( ) ;
135
+ let bodyHeight = this . _platform . height ( ) ;
129
136
130
- // console.log("Popover Wrapper Element", popoverWrapperEle);
131
- // console.log("Popover Wrapper Width & Height", popoverWidth, popoverHeight);
132
- // console.log("Body Width & Height", bodyWidth, bodyHeight);
133
- // console.log("Target", targetEle);
134
- // console.log("Target Width & Height", targetWidth, targetHeight);
135
-
136
- let popoverCSS = {
137
- top : ev . clientY + targetHeight - ( popoverHeight / 2 ) ,
138
- left : ev . clientX - popoverWidth / 2
139
- } ;
137
+ // Target element width and height
138
+ let targetDim = ev . target . getBoundingClientRect ( ) ;
139
+ let targetTop = targetDim . top ;
140
+ let targetLeft = targetDim . left ;
141
+ let targetWidth = targetDim . width ;
142
+ let targetHeight = targetDim . height ;
140
143
141
144
// The arrow that shows above the popover on iOS
142
- var arrowEle = popoverEle . querySelector ( '.popover-arrow' ) ;
143
- var arrowWidth = arrowEle . offsetWidth ;
144
- var arrowHeight = arrowEle . offsetHeight ;
145
-
146
- let arrowLeft = targetWidth + targetWidth / 2 -
147
- arrowEle . offsetWidth / 2 - popoverCSS . left ;
145
+ var arrowEle = nativeEle . querySelector ( '.popover-arrow' ) ;
146
+ let arrowDim = arrowEle . getBoundingClientRect ( ) ;
147
+ var arrowWidth = arrowDim . width ;
148
+ var arrowHeight = arrowDim . height ;
148
149
149
150
let arrowCSS = {
150
- top : ev . clientY + targetHeight - ( popoverHeight / 2 ) - arrowHeight ,
151
- left : ev . clientX - ( arrowWidth / 2 )
151
+ top : targetTop + targetHeight ,
152
+ left : targetLeft + ( targetWidth / 2 ) - ( arrowWidth / 2 )
152
153
}
153
154
155
+ let popoverCSS = {
156
+ top : targetTop + targetHeight + ( arrowHeight - 1 ) ,
157
+ left : targetLeft + ( targetWidth / 2 ) - ( popoverWidth / 2 )
158
+ } ;
159
+
154
160
// If the popover left is less than the padding it is off screen
155
161
// to the left so adjust it, else if the width of the popover
156
162
// exceeds the body width it is off screen to the right so adjust
157
163
if ( popoverCSS . left < POPOVER_BODY_PADDING ) {
158
164
popoverCSS . left = POPOVER_BODY_PADDING ;
159
- arrowCSS . left = ( POPOVER_BODY_PADDING * 2 ) ;
160
165
} else if ( popoverWidth + POPOVER_BODY_PADDING + popoverCSS . left > bodyWidth ) {
161
166
popoverCSS . left = bodyWidth - popoverWidth - POPOVER_BODY_PADDING ;
162
- arrowCSS . left = bodyWidth - ( POPOVER_BODY_PADDING * 2 ) - arrowWidth ;
163
167
}
164
168
165
169
// If the popover when popped down stretches past bottom of screen,
166
170
// make it pop up if there's room above
167
- if ( popoverCSS . top + POPOVER_BODY_PADDING + popoverHeight > bodyHeight &&
168
- popoverCSS . top - popoverHeight > 0 ) {
169
- popoverCSS . top = popoverCSS . top - targetHeight - popoverHeight ;
170
- this . _renderer . setElementClass ( this . _elementRef . nativeElement , 'popover-bottom' , true ) ;
171
+ if ( popoverCSS . top + POPOVER_BODY_PADDING + popoverHeight > bodyHeight && popoverCSS . top - popoverHeight > 0 ) {
172
+ arrowCSS . top = targetTop - ( arrowHeight + 1 ) ;
173
+ popoverCSS . top = targetTop - popoverHeight - ( arrowHeight - 1 ) ;
174
+ this . _renderer . setElementClass ( this . _elementRef . nativeElement , 'popover-bottom' , true ) ;
171
175
}
172
176
173
177
this . _renderer . setElementStyle ( arrowEle , 'top' , arrowCSS . top + 'px' ) ;
174
178
this . _renderer . setElementStyle ( arrowEle , 'left' , arrowCSS . left + 'px' ) ;
175
179
176
- this . _renderer . setElementStyle ( popoverWrapperEle , 'top' , popoverCSS . top + 'px' ) ;
177
- this . _renderer . setElementStyle ( popoverWrapperEle , 'left' , popoverCSS . left + 'px' ) ;
180
+ this . _renderer . setElementStyle ( popoverEle , 'top' , popoverCSS . top + 'px' ) ;
181
+ this . _renderer . setElementStyle ( popoverEle , 'left' , popoverCSS . left + 'px' ) ;
178
182
}
179
183
180
184
dismiss ( role ) : Promise < any > {
@@ -194,8 +198,6 @@ class PopoverCmp {
194
198
}
195
199
196
200
export interface PopoverOptions {
197
- template ?: string ;
198
- element ?: any ;
199
201
event ?: any ;
200
202
cssClass ?: string ;
201
203
showBackdrop ?: boolean ;
@@ -209,6 +211,8 @@ class PopoverPopIn extends Transition {
209
211
constructor ( enteringView : ViewController , leavingView : ViewController , opts : TransitionOptions ) {
210
212
super ( opts ) ;
211
213
214
+ console . log ( opts ) ;
215
+
212
216
let ele = enteringView . pageRef ( ) . nativeElement ;
213
217
let backdrop = new Animation ( ele . querySelector ( '.backdrop' ) ) ;
214
218
let wrapper = new Animation ( ele . querySelector ( '.popover-wrapper' ) ) ;
0 commit comments