diff --git a/ionic/components/nav/test/basic/pages/first-page.js b/ionic/components/nav/test/basic/pages/first-page.js index c0f920c471..05c2129c16 100644 --- a/ionic/components/nav/test/basic/pages/first-page.js +++ b/ionic/components/nav/test/basic/pages/first-page.js @@ -1,7 +1,8 @@ import {IonicComponent, IonicView, IonicConfig, IonicApp, Routable} from 'ionic/ionic'; import {NavParams, NavController} from 'ionic/ionic'; -import {SecondPage} from './second-page' +import {SecondPage} from './second-page'; +import {ThirdPage} from './third-page'; @IonicComponent({ @@ -23,6 +24,7 @@ import {SecondPage} from './second-page' '

First Page: {{ val }}

' + '

' + '

' + + '

' + '' + '' + '' + @@ -45,6 +47,14 @@ export class FirstPage { } } + setItems() { + let items = [ + ThirdPage + ]; + + this.nav.setItems(items); + } + viewLoaded() { console.log('viewLoaded first page'); } diff --git a/ionic/components/nav/test/basic/pages/second-page.js b/ionic/components/nav/test/basic/pages/second-page.js index d619217dc5..bcfe495f40 100644 --- a/ionic/components/nav/test/basic/pages/second-page.js +++ b/ionic/components/nav/test/basic/pages/second-page.js @@ -1,5 +1,6 @@ import {IonicComponent, IonicView, Routable, NavController, NavParams} from 'ionic/ionic'; import {ThirdPage} from './third-page'; +import {FirstPage} from './first-page'; @IonicComponent({ @@ -12,18 +13,11 @@ import {ThirdPage} from './third-page'; template: ` Second Page Header -

- -

-

- -

-

- -

-

- Random: {{ val }} -

+

+

+

+

+

Random: {{ val }}

` @@ -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';