diff --git a/packages/core/src/components/loading-controller/loading-controller.tsx b/packages/core/src/components/loading-controller/loading-controller.tsx index d00cde2925..ab8f5c7304 100644 --- a/packages/core/src/components/loading-controller/loading-controller.tsx +++ b/packages/core/src/components/loading-controller/loading-controller.tsx @@ -1,5 +1,5 @@ import { Component, Listen, Method } from '@stencil/core'; -import { Loading, LoadingEvent, LoadingOptions } from '../../index'; +import { LoadingEvent, LoadingOptions } from '../../index'; @Component({ @@ -8,13 +8,13 @@ import { Loading, LoadingEvent, LoadingOptions } from '../../index'; export class LoadingController { private ids = 0; private loadingResolves: {[loadingId: string]: Function} = {}; - private loadings: Loading[] = []; + private loadings: HTMLIonLoadingElement[] = []; /** * Create a loading overlay and pass options to it */ @Method() - create(opts?: LoadingOptions): Promise { + create(opts?: LoadingOptions): Promise { // create ionic's wrapping ion-loading component const loading = document.createElement('ion-loading'); @@ -33,7 +33,7 @@ export class LoadingController { appRoot.appendChild(loading as any); // store the resolve function to be called later up when the loading loads - return new Promise(resolve => { + return new Promise(resolve => { this.loadingResolves[loading.loadingId] = resolve; }); } @@ -41,7 +41,7 @@ export class LoadingController { @Listen('body:ionLoadingDidLoad') protected didLoad(ev: LoadingEvent) { - const loading = ev.detail.loading; + const loading = ev.target as HTMLIonLoadingElement; const loadingResolve = this.loadingResolves[loading.loadingId]; if (loadingResolve) { loadingResolve(loading); @@ -52,13 +52,13 @@ export class LoadingController { @Listen('body:ionLoadingWillPresent') protected willPresent(ev: LoadingEvent) { - this.loadings.push(ev.detail.loading); + this.loadings.push(ev.target as HTMLIonLoadingElement); } @Listen('body:ionLoadingWillDismiss, body:ionLoadingDidUnload') protected willDismiss(ev: LoadingEvent) { - const index = this.loadings.indexOf(ev.detail.loading); + const index = this.loadings.indexOf(ev.target as HTMLIonLoadingElement); if (index > -1) { this.loadings.splice(index, 1); } diff --git a/packages/core/src/components/loading/loading.tsx b/packages/core/src/components/loading/loading.tsx index 42505dec17..a426ff105c 100644 --- a/packages/core/src/components/loading/loading.tsx +++ b/packages/core/src/components/loading/loading.tsx @@ -1,7 +1,17 @@ -import { Animation, AnimationBuilder, AnimationController, Config } from '../../index'; -import { Component, Element, Event, EventEmitter, Listen, Prop, State } from '@stencil/core'; +import { Component, 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 { createThemedClasses } from '../../utils/theme'; + import iosEnterAnimation from './animations/ios.enter'; import iosLeaveAnimation from './animations/ios.leave'; import mdEnterAnimation from './animations/md.enter'; @@ -30,32 +40,32 @@ export class Loading { /** * @output {LoadingEvent} Emitted after the loading has loaded. */ - @Event() ionLoadingDidLoad: EventEmitter; + @Event() ionLoadingDidLoad: EventEmitter; /** * @output {LoadingEvent} Emitted after the loading has presented. */ - @Event() ionLoadingDidPresent: EventEmitter; + @Event() ionLoadingDidPresent: EventEmitter; /** * @output {LoadingEvent} Emitted before the loading has presented. */ - @Event() ionLoadingWillPresent: EventEmitter; + @Event() ionLoadingWillPresent: EventEmitter; /** * @output {LoadingEvent} Emitted before the loading has dismissed. */ - @Event() ionLoadingWillDismiss: EventEmitter; + @Event() ionLoadingWillDismiss: EventEmitter; /** * @output {LoadingEvent} Emitted after the loading has dismissed. */ - @Event() ionLoadingDidDismiss: EventEmitter; + @Event() ionLoadingDidDismiss: EventEmitter; /** * @output {LoadingEvent} Emitted after the loading has unloaded. */ - @Event() ionLoadingDidUnload: EventEmitter; + @Event() ionLoadingDidUnload: EventEmitter; @State() private showSpinner: boolean = null; @State() private spinner: string; @@ -103,16 +113,16 @@ export class Loading { */ @Prop() leaveAnimation: AnimationBuilder; + /** + * Toggles whether animation should occur or not + */ + @Prop() animate: boolean; + /** * Present a loading overlay after it has been created */ + @Method() present() { - return new Promise(resolve => { - this._present(resolve); - }); - } - - private _present(resolve: Function) { if (this.animation) { this.animation.destroy(); this.animation = null; @@ -124,22 +134,26 @@ export class Loading { const animationBuilder = this.enterAnimation || this.config.get('loadingEnter', this.mode === 'ios' ? iosEnterAnimation : mdEnterAnimation); // build the animation and kick it off - this.animationCtrl.create(animationBuilder, this.el).then(animation => { + // build the animation and kick it off + return this.animationCtrl.create(animationBuilder, this.el).then(animation => { this.animation = animation; - - animation.onFinish((a: any) => { - a.destroy(); - this.componentDidEnter(); - resolve(); - - }).play(); + if (!this.animate) { + // if the duration is 0, it won't actually animate I don't think + // TODO - validate this + this.animation = animation.duration(0); + } + return playAnimationAsync(animation); + }).then((animation) => { + animation.destroy(); + this.componentDidEnter(); }); } /** * Dismiss a loading indicator programatically */ - dismiss() { + @Method() + dismiss(data?: any, role?: string) { clearTimeout(this.durationTimeout); if (this.animation) { @@ -147,27 +161,25 @@ export class Loading { this.animation = null; } - return new Promise(resolve => { - this.ionLoadingWillDismiss.emit({ loading: this }); + this.ionLoadingWillDismiss.emit({ + data, + role + }); - // get the user's animation fn if one was provided - const animationBuilder = this.leaveAnimation || this.config.get('loadingLeave', this.mode === 'ios' ? iosLeaveAnimation : mdLeaveAnimation); + const animationBuilder = this.leaveAnimation || this.config.get('loadingLeave', this.mode === 'ios' ? iosLeaveAnimation : mdLeaveAnimation); - // build the animation and kick it off - this.animationCtrl.create(animationBuilder, this.el).then(animation => { - this.animation = animation; - - animation.onFinish((a: any) => { - a.destroy(); - this.ionLoadingDidDismiss.emit({ loading: this }); - - Context.dom.write(() => { - this.el.parentNode.removeChild(this.el); - }); - - resolve(); - - }).play(); + return this.animationCtrl.create(animationBuilder, this.el).then(animation => { + this.animation = animation; + return playAnimationAsync(animation); + }).then((animation) => { + animation.destroy(); + return domControllerAsync(Context.dom.write, () => { + this.el.parentNode.removeChild(this.el); + }); + }).then(() => { + this.ionLoadingDidDismiss.emit({ + data, + role }); }); } @@ -273,10 +285,20 @@ export interface LoadingOptions { translucent?: boolean; } -export interface LoadingEvent extends Event { - detail: { - loading: Loading; - }; +export interface LoadingEvent extends CustomEvent { + detail: LoadingEventDetail; +} + +export interface LoadingEventDetail { + +} + +export interface LoadingDismissEventDetail extends OverlayDismissEventDetail { + // keep this just for the sake of static types and potential future extensions +} + +export interface LoadingDismissEvent extends OverlayDismissEvent { + // keep this just for the sake of static types and potential future extensions } export { diff --git a/packages/core/src/components/loading/test/basic/index.html b/packages/core/src/components/loading/test/basic/index.html index ce5f0ad831..4bc123ceba 100644 --- a/packages/core/src/components/loading/test/basic/index.html +++ b/packages/core/src/components/loading/test/basic/index.html @@ -56,21 +56,21 @@