@@ -3,14 +3,17 @@ import { NG_VALUE_ACCESSOR } from '@angular/forms';
3
3
4
4
import { ActionSheet } from '../action-sheet/action-sheet' ;
5
5
import { Alert } from '../alert/alert' ;
6
+ import { Popover } from '../popover/popover' ;
6
7
import { App } from '../app/app' ;
7
8
import { Config } from '../../config/config' ;
9
+ import { DeepLinker } from '../../navigation/deep-linker' ;
8
10
import { Form } from '../../util/form' ;
9
11
import { BaseInput } from '../../util/base-input' ;
10
12
import { isCheckedProperty , isTrueProperty , deepCopy , deepEqual } from '../../util/util' ;
11
13
import { Item } from '../item/item' ;
12
14
import { NavController } from '../../navigation/nav-controller' ;
13
15
import { Option } from '../option/option' ;
16
+ import { SelectPopover , SelectPopoverOption } from './select-popover-component' ;
14
17
15
18
export const SELECT_VALUE_ACCESSOR : any = {
16
19
provide : NG_VALUE_ACCESSOR ,
@@ -30,17 +33,18 @@ export const SELECT_VALUE_ACCESSOR: any = {
30
33
* The select component takes child `ion-option` components. If `ion-option` is not
31
34
* given a `value` attribute then it will use its text as the value.
32
35
*
33
- * If `ngModel` is bound to `ion-select`, the selected value will be based on the
36
+ * If `ngModel` is bound to `ion-select`, the selected value will be based on the
34
37
* bound value of the model. Otherwise, the `selected` attribute can be used on
35
38
* `ion-option` components.
36
39
*
37
40
* ### Interfaces
38
41
*
39
42
* By default, the `ion-select` uses the {@link ../../alert/AlertController AlertController API}
40
43
* to open up the overlay of options in an alert. The interface can be changed to use the
41
- * {@link ../../action-sheet/ActionSheetController ActionSheetController API} by passing
42
- * `action-sheet` to the `interface` property. Read the other sections for the limitations of the
43
- * action sheet interface.
44
+ * {@link ../../action-sheet/ActionSheetController ActionSheetController API} or
45
+ * {@link ../../popover/PopoverController PopoverController API} by passing `action-sheet` or `popover`,
46
+ * respectively, to the `interface` property. Read on to the other sections for the limitations
47
+ * of the different interfaces.
44
48
*
45
49
* ### Single Value: Radio Buttons
46
50
*
@@ -70,7 +74,7 @@ export const SELECT_VALUE_ACCESSOR: any = {
70
74
* selected option values. In the example below, because each option is not given
71
75
* a `value`, then it'll use its text as the value instead.
72
76
*
73
- * Note: the action sheet interface will not work with a multi-value select.
77
+ * Note: the ` action- sheet` and `popover` interfaces will not work with a multi-value select.
74
78
*
75
79
* ```html
76
80
* <ion-item>
@@ -96,19 +100,22 @@ export const SELECT_VALUE_ACCESSOR: any = {
96
100
* </ion-select>
97
101
* ```
98
102
*
99
- * The action sheet interface does not have an `OK` button, clicking
103
+ * The ` action- sheet` and `popover` interfaces do not have an `OK` button, clicking
100
104
* on any of the options will automatically close the overlay and select
101
105
* that value.
102
106
*
103
107
* ### Select Options
104
108
*
105
- * Since `ion-select` uses the `Alert` and `Action Sheet` interfaces, options can be
109
+ * Since `ion-select` uses the `Alert`, `Action Sheet` and `Popover ` interfaces, options can be
106
110
* passed to these components through the `selectOptions` property. This can be used
107
111
* to pass a custom title, subtitle, css class, and more. See the
108
- * {@link ../../alert/AlertController/#create AlertController API docs} and
109
- * {@link ../../action-sheet/ActionSheetController/#create ActionSheetController API docs}
112
+ * {@link ../../alert/AlertController/#create AlertController API docs},
113
+ * {@link ../../action-sheet/ActionSheetController/#create ActionSheetController API docs}, and
114
+ * {@link ../../popover/PopoverController/#create PopoverController API docs}
110
115
* for the properties that each interface accepts.
111
116
*
117
+ * For example, to change the `mode` of the overlay, pass it into `selectOptions`.
118
+ *
112
119
* ```html
113
120
* <ion-select [selectOptions]="selectOptions">
114
121
* ...
@@ -118,7 +125,8 @@ export const SELECT_VALUE_ACCESSOR: any = {
118
125
* ```ts
119
126
* this.selectOptions = {
120
127
* title: 'Pizza Toppings',
121
- * subTitle: 'Select your toppings'
128
+ * subTitle: 'Select your toppings',
129
+ * mode: 'md'
122
130
* };
123
131
* ```
124
132
*
@@ -176,7 +184,7 @@ export class Select extends BaseInput<string[]> implements AfterViewInit, OnDest
176
184
@Input ( ) selectOptions : any = { } ;
177
185
178
186
/**
179
- * @input {string} The interface the select should use: `action-sheet` or `alert`. Default: `alert`.
187
+ * @input {string} The interface the select should use: `action-sheet`, `popover` or `alert`. Default: `alert`.
180
188
*/
181
189
@Input ( ) interface : string = '' ;
182
190
@@ -197,7 +205,8 @@ export class Select extends BaseInput<string[]> implements AfterViewInit, OnDest
197
205
elementRef : ElementRef ,
198
206
renderer : Renderer ,
199
207
@Optional ( ) item : Item ,
200
- @Optional ( ) private _nav : NavController
208
+ @Optional ( ) private _nav : NavController ,
209
+ public deepLinker : DeepLinker
201
210
) {
202
211
super ( config , elementRef , renderer , 'select' , [ ] , form , item , null ) ;
203
212
}
@@ -215,7 +224,7 @@ export class Select extends BaseInput<string[]> implements AfterViewInit, OnDest
215
224
}
216
225
ev . preventDefault ( ) ;
217
226
ev . stopPropagation ( ) ;
218
- this . open ( ) ;
227
+ this . open ( ev ) ;
219
228
}
220
229
221
230
@HostListener ( 'keyup.space' )
@@ -226,7 +235,7 @@ export class Select extends BaseInput<string[]> implements AfterViewInit, OnDest
226
235
/**
227
236
* Open the select interface.
228
237
*/
229
- open ( ) {
238
+ open ( ev ?: UIEvent ) {
230
239
if ( this . isFocus ( ) || this . _disabled ) {
231
240
return ;
232
241
}
@@ -257,12 +266,18 @@ export class Select extends BaseInput<string[]> implements AfterViewInit, OnDest
257
266
this . interface = 'alert' ;
258
267
}
259
268
260
- if ( this . interface === 'action-sheet' && this . _multi ) {
261
- console . warn ( 'Interface cannot be "action-sheet " with a multi-value select. Using the "alert" interface.' ) ;
269
+ if ( ( this . interface === 'action-sheet' || this . interface === 'popover' ) && this . _multi ) {
270
+ console . warn ( 'Interface cannot be "' + this . interface + ' " with a multi-value select. Using the "alert" interface.') ;
262
271
this . interface = 'alert' ;
263
272
}
264
273
265
- let overlay : ActionSheet | Alert ;
274
+ if ( this . interface === 'popover' && ! ev ) {
275
+ console . warn ( 'Interface cannot be "popover" without UIEvent.' ) ;
276
+ this . interface = 'alert' ;
277
+ }
278
+
279
+ let overlay : ActionSheet | Alert | Popover ;
280
+
266
281
if ( this . interface === 'action-sheet' ) {
267
282
selectOptions . buttons = selectOptions . buttons . concat ( options . map ( input => {
268
283
return {
@@ -282,6 +297,25 @@ export class Select extends BaseInput<string[]> implements AfterViewInit, OnDest
282
297
selectOptions . cssClass = selectCssClass ;
283
298
overlay = new ActionSheet ( this . _app , selectOptions , this . config ) ;
284
299
300
+ } else if ( this . interface === 'popover' ) {
301
+ let popoverOptions : SelectPopoverOption [ ] = options . map ( input => ( {
302
+ text : input . text ,
303
+ checked : input . selected ,
304
+ disabled : input . disabled ,
305
+ value : input . value
306
+ } ) ) ;
307
+
308
+ overlay = new Popover ( this . _app , SelectPopover , {
309
+ options : popoverOptions
310
+ } , {
311
+ cssClass : 'select-popover'
312
+ } , this . config , this . deepLinker ) ;
313
+
314
+ // ev.target is readonly.
315
+ // place popover regarding to ion-select instead of .button-inner
316
+ Object . defineProperty ( ev , 'target' , { value : ev . currentTarget } ) ;
317
+ selectOptions . ev = ev ;
318
+
285
319
} else {
286
320
// default to use the alert interface
287
321
this . interface = 'alert' ;
@@ -330,9 +364,15 @@ export class Select extends BaseInput<string[]> implements AfterViewInit, OnDest
330
364
}
331
365
332
366
overlay . present ( selectOptions ) ;
367
+
333
368
this . _fireFocus ( ) ;
334
- overlay . onDidDismiss ( ( ) => {
369
+ overlay . onDidDismiss ( ( value : any ) => {
335
370
this . _fireBlur ( ) ;
371
+
372
+ if ( this . interface === 'popover' && value ) {
373
+ this . value = value ;
374
+ this . ionChange . emit ( value ) ;
375
+ }
336
376
} ) ;
337
377
}
338
378
0 commit comments