Skip to content

Commit d3fa29f

Browse files
committed
feat(loading): add internal stack for the loading service
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
1 parent f096cf6 commit d3fa29f

File tree

6 files changed

+74
-9
lines changed

6 files changed

+74
-9
lines changed

ionic/components/loading/loading.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,12 @@ export class Loading extends ViewController {
9999

100100
constructor(opts: LoadingOptions = {}) {
101101
opts.showBackdrop = isPresent(opts.showBackdrop) ? !!opts.showBackdrop : true;
102+
opts.dismissOnPageChange = isPresent(opts.dismissOnPageChange) ? !!opts.dismissOnPageChange : false;
102103

103104
super(LoadingCmp, opts);
104105
this.viewType = 'loading';
105106
this.isOverlay = true;
107+
this.usePortal = true;
106108

107109
// by default, loading indicators should not fire lifecycle events of other views
108110
// for example, when an loading indicators enters, the current active view should

ionic/components/nav/nav-controller.ts

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {Keyboard} from '../../util/keyboard';
88
import {NavParams} from './nav-params';
99
import {NavRouter} from './nav-router';
1010
import {pascalCaseToDashCase, isTrueProperty, isBlank} from '../../util/util';
11+
import {Portal} from './nav-portal';
1112
import {raf} from '../../util/dom';
1213
import {SwipeBackGesture} from './swipe-back';
1314
import {Transition} from '../../transitions/transition';
@@ -109,6 +110,7 @@ export class NavController extends Ion {
109110
private _trans: Transition;
110111
private _sbGesture: SwipeBackGesture;
111112
private _sbThreshold: number;
113+
private _portal: Portal;
112114

113115
protected _sbEnabled: boolean;
114116
protected _ids: number = -1;
@@ -170,6 +172,10 @@ export class NavController extends Ion {
170172
provide(NavController, {useValue: this})
171173
]);
172174
}
175+
176+
setPortal(val: Portal) {
177+
this._portal = val;
178+
}
173179

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

@@ -433,7 +439,12 @@ export class NavController extends Ion {
433439
keyboardClose: false,
434440
direction: 'back',
435441
animation: enteringView.getTransitionName('back')
436-
});
442+
});
443+
444+
if (enteringView.usePortal && this._portal) {
445+
this._portal.present(enteringView);
446+
return;
447+
}
437448

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

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

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

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

12491260
// see if we should add the swipe back gesture listeners or not
12501261
this._sbCheck();
1262+
1263+
if (this._portal) {
1264+
this._portal._views.forEach(view => {
1265+
if (view.data && view.data.dismissOnPageChange) {
1266+
view.dismiss();
1267+
}
1268+
});
1269+
}
12511270

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

16411660
} else {
16421661
// this is the initial view
1643-
enteringView.setZIndex(INIT_ZINDEX, this._renderer);
1662+
enteringView.setZIndex(this._portal ? INIT_ZINDEX : PORTAL_ZINDEX, this._renderer);
16441663
}
16451664

16461665
} else if (direction === 'back') {
@@ -1680,5 +1699,6 @@ const STATE_REMOVE = 'remove';
16801699
const STATE_REMOVE_AFTER_TRANS = 'remove_after_trans';
16811700
const STATE_FORCE_ACTIVE = 'force_active';
16821701
const INIT_ZINDEX = 100;
1702+
const PORTAL_ZINDEX = 9999;
16831703

16841704
let ctrlIds = -1;

ionic/components/nav/nav-portal.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import {Directive, ElementRef, Input, Optional, NgZone, Compiler, AppViewManager, Renderer, Type, ContentChild} from 'angular2/core';
2+
3+
import {IonicApp} from '../app/app';
4+
import {Config} from '../../config/config';
5+
import {Keyboard} from '../../util/keyboard';
6+
import {NavController} from './nav-controller';
7+
import {ViewController} from './view-controller';
8+
9+
/**
10+
* @private
11+
*/
12+
@Directive({
13+
selector: '[portal]'
14+
})
15+
export class Portal extends NavController {
16+
constructor(
17+
@Optional() hostNavCtrl: NavController,
18+
@Optional() viewCtrl: ViewController,
19+
app: IonicApp,
20+
config: Config,
21+
keyboard: Keyboard,
22+
elementRef: ElementRef,
23+
compiler: Compiler,
24+
viewManager: AppViewManager,
25+
zone: NgZone,
26+
renderer: Renderer
27+
) {
28+
super(hostNavCtrl, app, config, keyboard, elementRef, null, compiler, viewManager, zone, renderer);
29+
}
30+
}

ionic/components/nav/nav.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import {Component, ElementRef, Input, Optional, NgZone, Compiler, AppViewManager, Renderer, Type} from 'angular2/core';
1+
import {Component, ElementRef, Input, Optional, NgZone, Compiler, AppViewManager, Renderer, Type, ViewChild} from 'angular2/core';
22

33
import {IonicApp} from '../app/app';
44
import {Config} from '../../config/config';
55
import {Keyboard} from '../../util/keyboard';
66
import {isTrueProperty} from '../../util/util';
77
import {NavController} from './nav-controller';
8+
import {Portal} from './nav-portal';
89
import {ViewController} from './view-controller';
910

1011
/**
@@ -104,7 +105,8 @@ import {ViewController} from './view-controller';
104105
*/
105106
@Component({
106107
selector: 'ion-nav',
107-
template: '<div #contents></div>'
108+
template: '<div #contents></div><div portal></div>',
109+
directives: [Portal]
108110
})
109111
export class Nav extends NavController {
110112
private _root: Type;
@@ -172,5 +174,9 @@ export class Nav extends NavController {
172174
this.push(this._root);
173175
}
174176
}
175-
177+
178+
@ViewChild(Portal)
179+
private set _navPortal(val: Portal) {
180+
this.setPortal(val);
181+
}
176182
}

ionic/components/nav/test/nav-controller.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,6 +1236,8 @@ export function run() {
12361236
setElementClass: function(){},
12371237
setElementStyle: function(){}
12381238
};
1239+
1240+
nav._portal = new NavController(null, null, config, null, elementRef, null, null, null, null, null);
12391241

12401242
return nav;
12411243
}

ionic/components/nav/view-controller.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ export class ViewController {
7777
*/
7878
isOverlay: boolean = false;
7979

80+
/**
81+
* @private
82+
*/
83+
usePortal: boolean = false;
84+
8085
/**
8186
* @private
8287
*/

0 commit comments

Comments
 (0)