import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; import { Animation, AnimationBuilder, Config, CssClassMap, Mode, OverlayEventDetail, OverlayInterface, PickerButton, PickerColumn } from '../../interface'; import { dismiss, eventMethod, present } from '../../utils/overlays'; import { createThemedClasses, getClassMap } from '../../utils/theme'; import { iosEnterAnimation } from './animations/ios.enter'; import { iosLeaveAnimation } from './animations/ios.leave'; @Component({ tag: 'ion-picker', styleUrls: { ios: 'picker.ios.scss', md: 'picker.md.scss' } }) export class Picker implements OverlayInterface { private durationTimeout: any; presented = false; animation?: Animation; @Element() el!: HTMLElement; @Prop({ connect: 'ion-animation-controller' }) animationCtrl!: HTMLIonAnimationControllerElement; @Prop({ context: 'config' }) config!: Config; /** @hidden */ @Prop() overlayIndex!: number; /** * The mode determines which platform styles to use. * Possible values are: `"ios"` or `"md"`. */ @Prop() mode!: Mode; /** * If true, the keyboard will be automatically dismissed when the overlay is presented. */ @Prop() keyboardClose = true; /** * Animation to use when the picker is presented. */ @Prop() enterAnimation?: AnimationBuilder; /** * Animation to use when the picker is dismissed. */ @Prop() leaveAnimation?: AnimationBuilder; /** * Array of buttons to be displayed at the top of the picker. */ @Prop() buttons: PickerButton[] = []; /** * Array of columns to be displayed in the picker. */ @Prop() columns: PickerColumn[] = []; /** * Additional classes to apply for custom CSS. If multiple classes are * provided they should be separated by spaces. */ @Prop() cssClass?: string | string[]; /** * Number of milliseconds to wait before dismissing the picker. */ @Prop() duration?: number; /** * If true, a backdrop will be displayed behind the picker. Defaults to `true`. */ @Prop() showBackdrop = true; /** * If true, the picker will be dismissed when the backdrop is clicked. Defaults to `true`. */ @Prop() backdropDismiss = true; /** * If true, the picker will animate. Defaults to `true`. */ @Prop() animated = true; /** * Emitted after the picker has loaded. */ @Event() ionPickerDidLoad!: EventEmitter; /** * Emitted after the picker has presented. */ @Event({ eventName: 'ionPickerDidPresent' }) didPresent!: EventEmitter; /** * Emitted before the picker has presented. */ @Event({ eventName: 'ionPickerWillPresent' }) willPresent!: EventEmitter; /** * Emitted before the picker has dismissed. */ @Event({ eventName: 'ionPickerWillDismiss' }) willDismiss!: EventEmitter; /** * Emitted after the picker has dismissed. */ @Event({ eventName: 'ionPickerDidDismiss' }) didDismiss!: EventEmitter; /** * Emitted after the picker has unloaded. */ @Event() ionPickerDidUnload!: EventEmitter; componentDidLoad() { this.ionPickerDidLoad.emit(); } componentDidUnload() { this.ionPickerDidUnload.emit(); } @Listen('ionBackdropTap') protected onBackdropTap() { const cancelBtn = this.buttons.find(b => b.role === 'cancel'); if (cancelBtn) { this.buttonClick(cancelBtn); } else { this.dismiss(); } } /** * Present the picker overlay after it has been created. */ @Method() async present(): Promise { await present( this, 'pickerEnter', iosEnterAnimation, iosEnterAnimation, undefined ); if (this.duration) { this.durationTimeout = setTimeout(() => this.dismiss(), this.duration); } } /** * Dismiss the picker overlay after it has been presented. */ @Method() dismiss(data?: any, role?: string): Promise { if (this.durationTimeout) { clearTimeout(this.durationTimeout); } return dismiss( this, data, role, 'pickerLeave', iosLeaveAnimation, iosLeaveAnimation ); } /** * Returns a promise that resolves when the picker did dismiss. It also accepts a callback * that is called in the same circustances. * */ @Method() onDidDismiss(): Promise { return eventMethod(this.el, 'ionPickerDidDismiss'); } /** * Returns a promise that resolves when the picker will dismiss. It also accepts a callback * that is called in the same circustances. * */ @Method() onWillDismiss(): Promise { return eventMethod(this.el, 'ionPickerWillDismiss'); } /** * Returns the column the matches the specified name */ @Method() getColumn(name: string): Promise { return Promise.resolve(this.columns.find(column => column.name === name)); } private buttonClick(button: PickerButton) { // if (this.disabled) { // return; // } // keep the time of the most recent button click let shouldDismiss = true; if (button.handler) { // a handler has been provided, execute it // pass the handler the values from the inputs if (button.handler(this.getSelected()) === false) { // if the return value of the handler is false then do not dismiss shouldDismiss = false; } } if (shouldDismiss) { this.dismiss(); } } private getSelected() { const selected: { [k: string]: any } = {}; this.columns.forEach((col, index) => { const selectedColumn = col.selectedIndex != null ? col.options[col.selectedIndex] : null; selected[col.name] = { text: selectedColumn ? selectedColumn.text : null, value: selectedColumn ? selectedColumn.value : null, columnIndex: index }; }); return selected; } hostData() { return { class: { ...createThemedClasses(this.mode, 'picker'), ...getClassMap(this.cssClass) }, style: { zIndex: 20000 + this.overlayIndex } }; } render() { const buttons = this.buttons.map(b => { return (typeof b === 'string') ? { text: b } : b; }); const columns = this.columns; return [ ,