Skip to content

Commit

Permalink
feat(loading): add internal stack for the loading service
Browse files Browse the repository at this point in the history
this allows the user to push multiple loading indicators on top of each
other without interfering with the page stack, as well as navigation
between pages behind the loading indicator.

references #5426
  • Loading branch information
brandyscarney committed Apr 5, 2016
1 parent f096cf6 commit d3fa29f
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 9 deletions.
2 changes: 2 additions & 0 deletions ionic/components/loading/loading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,12 @@ export class Loading extends ViewController {

constructor(opts: LoadingOptions = {}) {
opts.showBackdrop = isPresent(opts.showBackdrop) ? !!opts.showBackdrop : true;
opts.dismissOnPageChange = isPresent(opts.dismissOnPageChange) ? !!opts.dismissOnPageChange : false;

super(LoadingCmp, opts);
this.viewType = 'loading';
this.isOverlay = true;
this.usePortal = true;

// by default, loading indicators should not fire lifecycle events of other views
// for example, when an loading indicators enters, the current active view should
Expand Down
32 changes: 26 additions & 6 deletions ionic/components/nav/nav-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {Keyboard} from '../../util/keyboard';
import {NavParams} from './nav-params';
import {NavRouter} from './nav-router';
import {pascalCaseToDashCase, isTrueProperty, isBlank} from '../../util/util';
import {Portal} from './nav-portal';
import {raf} from '../../util/dom';
import {SwipeBackGesture} from './swipe-back';
import {Transition} from '../../transitions/transition';
Expand Down Expand Up @@ -109,6 +110,7 @@ export class NavController extends Ion {
private _trans: Transition;
private _sbGesture: SwipeBackGesture;
private _sbThreshold: number;
private _portal: Portal;

protected _sbEnabled: boolean;
protected _ids: number = -1;
Expand Down Expand Up @@ -170,6 +172,10 @@ export class NavController extends Ion {
provide(NavController, {useValue: this})
]);
}

setPortal(val: Portal) {
this._portal = val;
}

/**
* Set the root for the current navigation stack
Expand Down Expand Up @@ -412,7 +418,7 @@ export class NavController extends Ion {
if (rootNav['_tabs']) {
// TODO: must have until this goes in
// https://github.com/angular/angular/issues/5481
console.error('A parent <ion-nav> is required for ActionSheet/Alert/Modal');
console.error('A parent <ion-nav> is required for ActionSheet/Alert/Modal/Loading');
return;
}

Expand All @@ -433,7 +439,12 @@ export class NavController extends Ion {
keyboardClose: false,
direction: 'back',
animation: enteringView.getTransitionName('back')
});
});

if (enteringView.usePortal && this._portal) {
this._portal.present(enteringView);
return;
}

// start the transition
return rootNav._insertViews(-1, [enteringView], opts);
Expand Down Expand Up @@ -534,7 +545,7 @@ export class NavController extends Ion {

if (this._views[i] === enteringView) {
// cool, so the last valid view is also our entering view!!
// this means we should animate that bad boy in so its the active view
// this means we should animate that bad boy in so it's the active view
// return a promise and resolve when the transition has completed

// get the leaving view which the _insert() already set
Expand Down Expand Up @@ -730,8 +741,8 @@ export class NavController extends Ion {
// get the view thats ready to enter
let enteringView = this.getByState(STATE_INIT_ENTER);

if (!enteringView) {
// oh knows! no entering view to go to!
if (!enteringView && this._portal) {
// oh nos! no entering view to go to!
// if there is no previous view that would enter in this nav stack
// and the option is set to climb up the nav parent looking
// for the next nav we could transition to instead
Expand Down Expand Up @@ -1248,6 +1259,14 @@ export class NavController extends Ion {

// see if we should add the swipe back gesture listeners or not
this._sbCheck();

if (this._portal) {
this._portal._views.forEach(view => {
if (view.data && view.data.dismissOnPageChange) {
view.dismiss();
}
});
}

} else {
// darn, so this wasn't the most recent transition
Expand Down Expand Up @@ -1640,7 +1659,7 @@ export class NavController extends Ion {

} else {
// this is the initial view
enteringView.setZIndex(INIT_ZINDEX, this._renderer);
enteringView.setZIndex(this._portal ? INIT_ZINDEX : PORTAL_ZINDEX, this._renderer);
}

} else if (direction === 'back') {
Expand Down Expand Up @@ -1680,5 +1699,6 @@ const STATE_REMOVE = 'remove';
const STATE_REMOVE_AFTER_TRANS = 'remove_after_trans';
const STATE_FORCE_ACTIVE = 'force_active';
const INIT_ZINDEX = 100;
const PORTAL_ZINDEX = 9999;

let ctrlIds = -1;
30 changes: 30 additions & 0 deletions ionic/components/nav/nav-portal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {Directive, ElementRef, Input, Optional, NgZone, Compiler, AppViewManager, Renderer, Type, ContentChild} from 'angular2/core';

import {IonicApp} from '../app/app';
import {Config} from '../../config/config';
import {Keyboard} from '../../util/keyboard';
import {NavController} from './nav-controller';
import {ViewController} from './view-controller';

/**
* @private
*/
@Directive({
selector: '[portal]'
})
export class Portal extends NavController {
constructor(
@Optional() hostNavCtrl: NavController,
@Optional() viewCtrl: ViewController,
app: IonicApp,
config: Config,
keyboard: Keyboard,
elementRef: ElementRef,
compiler: Compiler,
viewManager: AppViewManager,
zone: NgZone,
renderer: Renderer
) {
super(hostNavCtrl, app, config, keyboard, elementRef, null, compiler, viewManager, zone, renderer);
}
}
12 changes: 9 additions & 3 deletions ionic/components/nav/nav.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import {Component, ElementRef, Input, Optional, NgZone, Compiler, AppViewManager, Renderer, Type} from 'angular2/core';
import {Component, ElementRef, Input, Optional, NgZone, Compiler, AppViewManager, Renderer, Type, ViewChild} from 'angular2/core';

import {IonicApp} from '../app/app';
import {Config} from '../../config/config';
import {Keyboard} from '../../util/keyboard';
import {isTrueProperty} from '../../util/util';
import {NavController} from './nav-controller';
import {Portal} from './nav-portal';
import {ViewController} from './view-controller';

/**
Expand Down Expand Up @@ -104,7 +105,8 @@ import {ViewController} from './view-controller';
*/
@Component({
selector: 'ion-nav',
template: '<div #contents></div>'
template: '<div #contents></div><div portal></div>',
directives: [Portal]
})
export class Nav extends NavController {
private _root: Type;
Expand Down Expand Up @@ -172,5 +174,9 @@ export class Nav extends NavController {
this.push(this._root);
}
}


@ViewChild(Portal)
private set _navPortal(val: Portal) {
this.setPortal(val);
}
}
2 changes: 2 additions & 0 deletions ionic/components/nav/test/nav-controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,8 @@ export function run() {
setElementClass: function(){},
setElementStyle: function(){}
};

nav._portal = new NavController(null, null, config, null, elementRef, null, null, null, null, null);

return nav;
}
Expand Down
5 changes: 5 additions & 0 deletions ionic/components/nav/view-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ export class ViewController {
*/
isOverlay: boolean = false;

/**
* @private
*/
usePortal: boolean = false;

/**
* @private
*/
Expand Down

0 comments on commit d3fa29f

Please sign in to comment.