`
@@ -40,6 +34,15 @@ export class SecondPage {
console.log('Second page params:', params);
}
+ setItems() {
+ let items = [
+ FirstPage,
+ ThirdPage
+ ];
+
+ this.nav.setItems(items);
+ }
+
pop() {
this.nav.pop();
}
diff --git a/ionic/components/view/view-controller.js b/ionic/components/view/view-controller.js
index e76240707d..e479ff0e8d 100644
--- a/ionic/components/view/view-controller.js
+++ b/ionic/components/view/view-controller.js
@@ -67,8 +67,11 @@ export class ViewController extends Ion {
// the active item is going to be the leaving one (if one exists)
let leavingItem = this.getActive() || new ViewItem();
- leavingItem.shouldDestroy = false;
- leavingItem.shouldCache = true;
+ leavingItem.shouldCache = (util.isBoolean(opts.cacheLeavingItem) ? opts.cacheLeavingItem : true);
+ leavingItem.shouldDestroy = !leavingItem.shouldCache;
+ if (leavingItem.shouldDestroy) {
+ leavingItem.willUnload();
+ }
// create a new ViewItem
let enteringItem = new ViewItem(this, ComponentType, params);
@@ -101,13 +104,15 @@ export class ViewController extends Ion {
// get the active item and set that it is staged to be leaving
// was probably the one popped from the stack
let leavingItem = this.getActive() || new ViewItem();
- leavingItem.shouldDestroy = true;
- leavingItem.shouldCache = false;
- leavingItem.willUnload();
+ leavingItem.shouldCache = (util.isBoolean(opts.cacheLeavingItem) ? opts.cacheLeavingItem : false);
+ leavingItem.shouldDestroy = !leavingItem.shouldCache;
+ if (leavingItem.shouldDestroy) {
+ leavingItem.willUnload();
+ }
// the entering item is now the new last item
- // Note: we might not have an entering item if this is the only
- // item on the history stack.
+ // Note: we might not have an entering item if this is the
+ // only item on the history stack.
let enteringItem = this.getPrevious(leavingItem);
if (enteringItem) {
// notify app of the state change
@@ -127,6 +132,51 @@ export class ViewController extends Ion {
return promise;
}
+ /**
+ * Set the item stack to reflect the given component classes.
+ */
+ setItems(components, opts = {}) {
+ // if animate has not been set then default to false
+ opts.animate = opts.animate || false;
+
+ // ensure leaving items are not cached, and should be destroyed
+ opts.cacheLeavingItem = false;
+
+ // get the items to auto remove without having to do a transiton for each
+ // the last item (the currently active one) will do a normal transition out
+ if (this.items.length > 1) {
+ let autoRemoveItems = this.items.slice(0, this.items.length - 1);
+ for (let i = 0; i < autoRemoveItems.length; i++) {
+ autoRemoveItems[i].shouldDestroy = true;
+ autoRemoveItems[i].shouldCache = false;
+ autoRemoveItems[i].willUnload();
+ }
+ }
+
+ let component = null;
+ let viewItem = null;
+
+ // create the ViewItems that go before the new active ViewItem in the stack
+ // but the previous views won't should render yet
+ if (components.length > 1) {
+ let newBeforeItems = components.slice(0, components.length - 1);
+ for (let j = 0; j < newBeforeItems.length; j++) {
+ component = newBeforeItems[j];
+ viewItem = new ViewItem(this, component.component || component, component.params);
+
+ // add the item to the stack
+ this.add(viewItem);
+ }
+ }
+
+ // get the component that will become the active item
+ // it'll be the last one in the given components array
+ component = components[ components.length - 1 ];
+
+ // transition the leaving and entering
+ return this.push(component.component || component, component.params, opts);
+ }
+
transition(enteringItem, leavingItem, opts, callback) {
if (!enteringItem || enteringItem === leavingItem) {
return callback();
@@ -432,44 +482,6 @@ export class ViewController extends Ion {
return this.items.length;
}
- /**
- * Set the item stack to reflect the given component classes.
- */
- setItems(components) {
- // Pop all of the current items
- this.clear();
-
-
- // Then, change the root
-
- let leavingItem = this.getActive() || new ViewItem();
- leavingItem.shouldDestroy = true;
- leavingItem.shouldCache = false;
- leavingItem.willUnload();
-
- this.transitionComplete();
-
- for(let c of components) {
- this.push(c, {
- animate: false
- })
- }
- }
-
- /**
- * Pops off all the trailing items, but leaves the root.
- * To change the root, call setRoot with the root component.
- */
- clear() {
- let pops = [];
- for (let item of this.items) {
- pops.push(this.pop({
- animate: false
- }));
- }
- return Promise.all(pops);
- }
-
instances() {
let instances = [];
for (let item of this.items) {
diff --git a/ionic/components/view/view-item.js b/ionic/components/view/view-item.js
index 5ff64bc9bb..6c5cfb10bc 100644
--- a/ionic/components/view/view-item.js
+++ b/ionic/components/view/view-item.js
@@ -146,7 +146,10 @@ export class ViewItem {
enableBack() {
// update if it's possible to go back from this nav item
if (this.viewCtrl) {
- return !!this.viewCtrl.getPrevious(this);
+ let previousItem = this.viewCtrl.getPrevious(this);
+ // the previous view may exist, but if it's about to be destroyed
+ // it shouldn't be able to go back to
+ return !!(previousItem && !previousItem.shouldDestroy);
}
return false;
}
diff --git a/ionic/util/util.js b/ionic/util/util.js
index 2f49ad864d..7034dc9b95 100644
--- a/ionic/util/util.js
+++ b/ionic/util/util.js
@@ -68,6 +68,7 @@ export function defaults(dest) {
return dest;
}
+export const isBoolean = val => typeof val === 'boolean';
export const isString = val => typeof val === 'string';
export const isNumber = val => typeof val === 'number';
export const isFunction = val => typeof val === 'function';