refactor(picker): update picker api and events to match other overlays

This commit is contained in:
Dan Bucholtz
2017-12-02 00:46:21 -06:00
parent 7bcb4dec54
commit 71ff57c536
2 changed files with 73 additions and 56 deletions

View File

@ -1,5 +1,5 @@
import { Component, Listen, Method } from '@stencil/core'; import { Component, Listen, Method } from '@stencil/core';
import { Picker, PickerEvent, PickerOptions } from '../../index'; import { PickerEvent, PickerOptions } from '../../index';
@Component({ @Component({
@ -8,10 +8,10 @@ import { Picker, PickerEvent, PickerOptions } from '../../index';
export class PickerController { export class PickerController {
private ids = 0; private ids = 0;
private pickerResolves: {[pickerId: string]: Function} = {}; private pickerResolves: {[pickerId: string]: Function} = {};
private pickers: Picker[] = []; private pickers: HTMLIonPickerElement[] = [];
@Method() @Method()
create(opts?: PickerOptions): Promise<Picker> { create(opts?: PickerOptions): Promise<HTMLIonPickerElement> {
// create ionic's wrapping ion-picker component // create ionic's wrapping ion-picker component
const picker = document.createElement('ion-picker'); const picker = document.createElement('ion-picker');
@ -30,7 +30,7 @@ export class PickerController {
appRoot.appendChild(picker as any); appRoot.appendChild(picker as any);
// store the resolve function to be called later up when the picker loads // store the resolve function to be called later up when the picker loads
return new Promise<Picker>(resolve => { return new Promise<HTMLIonPickerElement>(resolve => {
this.pickerResolves[picker.pickerId] = resolve; this.pickerResolves[picker.pickerId] = resolve;
}); });
} }
@ -38,7 +38,7 @@ export class PickerController {
@Listen('body:ionPickerDidLoad') @Listen('body:ionPickerDidLoad')
protected didLoad(ev: PickerEvent) { protected didLoad(ev: PickerEvent) {
const picker = ev.detail.picker; const picker = ev.target as HTMLIonPickerElement;
const pickerResolve = this.pickerResolves[picker.pickerId]; const pickerResolve = this.pickerResolves[picker.pickerId];
if (pickerResolve) { if (pickerResolve) {
pickerResolve(picker); pickerResolve(picker);
@ -49,13 +49,13 @@ export class PickerController {
@Listen('body:ionPickerWillPresent') @Listen('body:ionPickerWillPresent')
protected willPresent(ev: PickerEvent) { protected willPresent(ev: PickerEvent) {
this.pickers.push(ev.detail.picker); this.pickers.push(ev.target as HTMLIonPickerElement);
} }
@Listen('body:ionPickerWillDismiss, body:ionPickerDidUnload') @Listen('body:ionPickerWillDismiss, body:ionPickerDidUnload')
protected willDismiss(ev: PickerEvent) { protected willDismiss(ev: PickerEvent) {
const index = this.pickers.indexOf(ev.detail.picker); const index = this.pickers.indexOf(ev.target as HTMLIonPickerElement);
if (index > -1) { if (index > -1) {
this.pickers.splice(index, 1); this.pickers.splice(index, 1);
} }

View File

@ -1,6 +1,16 @@
import { Animation, AnimationBuilder, AnimationController, Config } from '../../index';
import { Component, CssClassMap, Element, Event, EventEmitter, Listen, Method, Prop, State } from '@stencil/core'; import { Component, CssClassMap, Element, Event, EventEmitter, Listen, Method, Prop, State } from '@stencil/core';
import {
Animation,
AnimationBuilder,
AnimationController,
Config,
OverlayDismissEvent,
OverlayDismissEventDetail
} from '../../index';
import { domControllerAsync, playAnimationAsync } from '../../utils/helpers';
import iosEnterAnimation from './animations/ios.enter'; import iosEnterAnimation from './animations/ios.enter';
import iosLeaveAnimation from './animations/ios.leave'; import iosLeaveAnimation from './animations/ios.leave';
@ -24,32 +34,32 @@ export class Picker {
/** /**
* @output {PickerEvent} Emitted after the picker has loaded. * @output {PickerEvent} Emitted after the picker has loaded.
*/ */
@Event() ionPickerDidLoad: EventEmitter; @Event() ionPickerDidLoad: EventEmitter<PickerEventDetail>;
/** /**
* @output {PickerEvent} Emitted after the picker has presented. * @output {PickerEvent} Emitted after the picker has presented.
*/ */
@Event() ionPickerDidPresent: EventEmitter; @Event() ionPickerDidPresent: EventEmitter<PickerEventDetail>;
/** /**
* @output {PickerEvent} Emitted before the picker has presented. * @output {PickerEvent} Emitted before the picker has presented.
*/ */
@Event() ionPickerWillPresent: EventEmitter; @Event() ionPickerWillPresent: EventEmitter<PickerEventDetail>;
/** /**
* @output {PickerEvent} Emitted before the picker has dismissed. * @output {PickerEvent} Emitted before the picker has dismissed.
*/ */
@Event() ionPickerWillDismiss: EventEmitter; @Event() ionPickerWillDismiss: EventEmitter<PickerDismissEventDetail>;
/** /**
* @output {PickerEvent} Emitted after the picker has dismissed. * @output {PickerEvent} Emitted after the picker has dismissed.
*/ */
@Event() ionPickerDidDismiss: EventEmitter; @Event() ionPickerDidDismiss: EventEmitter<PickerDismissEventDetail>;
/** /**
* @output {PickerEvent} Emitted after the picker has unloaded. * @output {PickerEvent} Emitted after the picker has unloaded.
*/ */
@Event() ionPickerDidUnload: EventEmitter; @Event() ionPickerDidUnload: EventEmitter<PickerEventDetail>;
@State() private showSpinner: boolean = null; @State() private showSpinner: boolean = null;
@State() private spinner: string; @State() private spinner: string;
@ -65,41 +75,40 @@ export class Picker {
@Prop() pickerId: string; @Prop() pickerId: string;
@Prop() showBackdrop: boolean = true; @Prop() showBackdrop: boolean = true;
@Prop() enableBackdropDismiss: boolean = true; @Prop() enableBackdropDismiss: boolean = true;
@Prop() animate: boolean;
@Prop() buttons: PickerButton[] = []; @Prop() buttons: PickerButton[] = [];
@Prop() columns: PickerColumn[] = []; @Prop() columns: PickerColumn[] = [];
@Method()
present() { present() {
return new Promise<void>(resolve => {
this._present(resolve);
});
}
private _present(resolve: Function) {
if (this.animation) { if (this.animation) {
this.animation.destroy(); this.animation.destroy();
this.animation = null; this.animation = null;
} }
this.ionPickerWillPresent.emit({ picker: this }); this.ionPickerWillPresent.emit();
// get the user's animation fn if one was provided // get the user's animation fn if one was provided
const animationBuilder = this.enterAnimation || this.config.get('pickerEnter', iosEnterAnimation); const animationBuilder = this.enterAnimation || this.config.get('pickerEnter', iosEnterAnimation);
// build the animation and kick it off // build the animation and kick it off
this.animationCtrl.create(animationBuilder, this.el).then(animation => { return this.animationCtrl.create(animationBuilder, this.el).then(animation => {
this.animation = animation; this.animation = animation;
if (!this.animate) {
animation.onFinish((a: any) => { // if the duration is 0, it won't actually animate I don't think
a.destroy(); // TODO - validate this
this.componentDidEnter(); this.animation = animation.duration(0);
resolve(); }
return playAnimationAsync(animation);
}).play(); }).then((animation) => {
animation.destroy();
this.componentDidEnter();
}); });
} }
dismiss() { @Method()
dismiss(data?: any, role?: string) {
clearTimeout(this.durationTimeout); clearTimeout(this.durationTimeout);
if (this.animation) { if (this.animation) {
@ -107,27 +116,25 @@ export class Picker {
this.animation = null; this.animation = null;
} }
return new Promise(resolve => { this.ionPickerWillDismiss.emit({
this.ionPickerWillDismiss.emit({ picker: this }); data,
role
});
// get the user's animation fn if one was provided const animationBuilder = this.leaveAnimation || this.config.get('pickerLeave', iosLeaveAnimation);
const animationBuilder = this.leaveAnimation || this.config.get('pickerLeave', iosLeaveAnimation);
// build the animation and kick it off return this.animationCtrl.create(animationBuilder, this.el).then(animation => {
this.animationCtrl.create(animationBuilder, this.el).then(animation => { this.animation = animation;
this.animation = animation; return playAnimationAsync(animation);
}).then((animation) => {
animation.onFinish((a: any) => { animation.destroy();
a.destroy(); return domControllerAsync(Context.dom.write, () => {
this.ionPickerDidDismiss.emit({ picker: this }); this.el.parentNode.removeChild(this.el);
});
Context.dom.write(() => { }).then(() => {
this.el.parentNode.removeChild(this.el); this.ionPickerDidDismiss.emit({
}); data,
role
resolve();
}).play();
}); });
}); });
} }
@ -146,7 +153,7 @@ export class Picker {
if (this.showSpinner === null || this.showSpinner === undefined) { if (this.showSpinner === null || this.showSpinner === undefined) {
this.showSpinner = !!(this.spinner && this.spinner !== 'hide'); this.showSpinner = !!(this.spinner && this.spinner !== 'hide');
} }
this.ionPickerDidLoad.emit({ picker: this }); this.ionPickerDidLoad.emit();
} }
componentDidEnter() { componentDidEnter() {
@ -159,11 +166,11 @@ export class Picker {
this.durationTimeout = setTimeout(() => this.dismiss(), this.duration); this.durationTimeout = setTimeout(() => this.dismiss(), this.duration);
} }
this.ionPickerDidPresent.emit({ picker: this }); this.ionPickerDidPresent.emit();
} }
componentDidUnload() { componentDidUnload() {
this.ionPickerDidUnload.emit({ picker: this }); this.ionPickerDidUnload.emit();
} }
@ -401,10 +408,20 @@ export interface PickerColumnOption {
selected?: boolean; selected?: boolean;
} }
export interface PickerEvent extends Event { export interface PickerEvent extends CustomEvent {
detail: { detail: PickerEventDetail;
picker: Picker; }
};
export interface PickerEventDetail {
}
export interface PickerDismissEventDetail extends OverlayDismissEventDetail {
// keep this just for the sake of static types and potential future extensions
}
export interface PickerDismissEvent extends OverlayDismissEvent {
// keep this just for the sake of static types and potential future extensions
} }
export { export {