diff --git a/ionic/components/nav/nav-base.js b/ionic/components/nav/nav-base.js index 2e183a0313..20628f24f2 100644 --- a/ionic/components/nav/nav-base.js +++ b/ionic/components/nav/nav-base.js @@ -1,6 +1,6 @@ -import {NgElement} from 'angular2/angular2'; import * as util from 'ionic/util'; import {Transition, ClickBlock} from 'ionic/ionic'; +import {NavItem} from './nav-item' const STAGED_STATE = 'staged'; @@ -12,85 +12,19 @@ const ACTIVE_STATE = 'active'; const CACHED_STATE = 'cached'; -/* - * Used by tabs and nav - */ export class NavBase { - constructor( - element: NgElement - ) { - this.domElement = element.domElement; - // this is our sane stack of items. This is synchronous and says an item - // is removed even if it's still animating out. - this._stack = []; - - // The navItems array is what add/remove components from the dom. - // These arrays won't remove a component until they're - // done animating out. - this.navItems = []; - } - - containsClass(Class) { - for (let i = 0; i < this._stack.length; i++) { - if (this._stack[i].Class === Class) { - return true; - } - } - return false; + constructor() { + this.items = []; } set initial(Class) { - if (!this.initialized) { - this.initialized = true + if (!this._init) { + this._init = true this.push(Class); } } - getActive() { - for (let i = 0, ii = this.navItems.length; i < ii; i++) { - if (this.navItems[i].state === ACTIVE_STATE) { - return this.navItems[i]; - } - } - return null; - } - - getPrevious(item) { - if (item) { - return this._stack[ this._stack.indexOf(item) - 1 ]; - } - return null; - } - - getStagedEnteringItem() { - for (let i = 0, ii = this.navItems.length; i < ii; i++) { - if (this.navItems[i].state === STAGED_ENTERING_STATE) { - return this.navItems[i]; - } - } - return null; - } - - getStagedLeavingItem() { - for (let i = 0, ii = this.navItems.length; i < ii; i++) { - if (this.navItems[i].state === STAGED_LEAVING_STATE) { - return this.navItems[i]; - } - } - return null; - } - - getLeavingItems() { - let items = []; - for (let i = 0, ii = this.navItems.length; i < ii; i++) { - if (this.navItems[i].state === ACTIVELY_LEAVING_STATE || this.navItems[i].state === STAGED_LEAVING_STATE) { - items.push(this.navItems[i]); - } - } - return items; - } - push(Class: Function, params = {}, opts = {}) { let resolve; let promise = new Promise(res => { resolve = res; }); @@ -99,7 +33,7 @@ export class NavBase { opts.direction = opts.direction || 'forward'; // do not animate if this is the first in the stack - if (!this._stack.length) { + if (!this.items.length) { opts.animation = 'none'; } @@ -107,14 +41,13 @@ export class NavBase { let leavingItem = this.getActive() || {}; // create a new NavStackItem - let enteringItem = new NavStackItem(Class, params); + let enteringItem = new NavItem(this, Class, params); // set that this item is staged (it's not ready to be animated in yet) enteringItem.state = STAGED_STATE; - // add the item to the stack (just renders in the DOM, doesn't animate yet) - this._stack.push(enteringItem); - this.navItems.push(enteringItem); + // add the item to the stack + this.items.push(enteringItem); // start the transition this.transition(enteringItem, leavingItem, opts).then(() => { @@ -132,7 +65,7 @@ export class NavBase { opts.direction = opts.direction || 'back'; // remove the last item - this._stack.pop(); + this.items.pop(); // the entering item is now the new last item let enteringItem = this.last() @@ -206,17 +139,64 @@ export class NavBase { return promise; } + + + + getActive() { + for (let i = 0, ii = this.items.length; i < ii; i++) { + if (this.items[i].state === ACTIVE_STATE) { + return this.items[i]; + } + } + return null; + } + + getPrevious(item) { + if (item) { + return this.items[ this.items.indexOf(item) - 1 ]; + } + return null; + } + + getStagedEnteringItem() { + for (let i = 0, ii = this.items.length; i < ii; i++) { + if (this.items[i].state === STAGED_ENTERING_STATE) { + return this.items[i]; + } + } + return null; + } + + getStagedLeavingItem() { + for (let i = 0, ii = this.items.length; i < ii; i++) { + if (this.items[i].state === STAGED_LEAVING_STATE) { + return this.items[i]; + } + } + return null; + } + + getLeavingItems() { + let items = []; + for (let i = 0, ii = this.items.length; i < ii; i++) { + if (this.items[i].state === ACTIVELY_LEAVING_STATE || this.items[i].state === STAGED_LEAVING_STATE) { + items.push(this.items[i]); + } + } + return items; + } + last() { - return this._stack[this._stack.length - 1] + return this.items[this.items.length - 1] } length() { - return this._stack.length; + return this.items.length; } popAll() { - while (this._stack.length) { - const item = this._stack.pop() + while (this.items.length) { + const item = this.items.pop() this._destroy(item) } } @@ -226,31 +206,31 @@ export class NavBase { // then performs a normal pop. popTo(index, opts = {}) { // Abort if we're already here. - if (this._stack.length <= index + 1) { + if (this.items.length <= index + 1) { return Promise.resolve(); } // Save the current navItem, and remove all the other ones in front of our // target nav item. - const current = this._stack.pop() - while (this._stack.length > index + 1) { - const item = this._stack.pop() + const current = this.items.pop() + while (this.items.length > index + 1) { + const item = this.items.pop() this._destroy(item) } // Now put the current navItem back on the stack and run a normal pop animation. - this._stack.push(current) + this.items.push(current) return this.pop(opts) } remove(index) { - const item = this._stack[index]; - this._stack.splice(index, 1); + const item = this.items[index]; + this.items.splice(index, 1); this._destroy(item); } _destroy(navItem) { - util.array.remove(this.navItems, navItem); + util.array.remove(this.items, navItem); } getToolbars(pos: String) { @@ -270,27 +250,3 @@ export class NavBase { return !!this.getPrevious(this.getActive()); } } - - -class NavStackItem { - - constructor(ComponentClass, params = {}) { - this.Class = ComponentClass; - this.params = params; - this.id = util.nextUid(); - this._setupPromise = new Promise((resolve) => { - this._resolveSetup = resolve; - }); - } - - setup() { - return this._setupPromise; - } - - finishSetup(navItem, componentInstance) { - this.navItem = navItem; - this.instance = componentInstance; - this._resolveSetup(); - } - -} diff --git a/ionic/components/nav/nav-controller.js b/ionic/components/nav/nav-controller.js new file mode 100644 index 0000000000..8701452d9c --- /dev/null +++ b/ionic/components/nav/nav-controller.js @@ -0,0 +1,13 @@ + +export class NavController { + constructor() { + } + + push() { + return this.nav.push.apply(this.nav, arguments); + } + + pop() { + return this.nav.pop.apply(this.nav, arguments); + } +} diff --git a/ionic/components/nav/nav-decorators.js b/ionic/components/nav/nav-decorators.js deleted file mode 100644 index 6b8dd90ada..0000000000 --- a/ionic/components/nav/nav-decorators.js +++ /dev/null @@ -1,33 +0,0 @@ -import { - Decorator, - View, - For, - NgElement, - Parent, - Ancestor -} from 'angular2/angular2'; -import {Optional} from 'angular2/di' -import {Nav} from 'ionic/ionic'; - -@Decorator({ - selector: '[push-to]' -}) -export class PushToNav { - constructor( - element: NgElement, - @Ancestor() viewportNav: Nav - ) { - console.log('PUSH TO NAV', element.domElement, viewportNav); - - this.navTag = element.domElement.getAttribute('push-to'); - console.log('PUSH TO NAV', this.navTag); - } -} - -@Decorator({ - selector: '[href]' -}) -export class HrefNav { - constructor(element: NgElement) { - } -} diff --git a/ionic/components/nav/nav-item.js b/ionic/components/nav/nav-item.js index ca5110d159..e065543c5e 100644 --- a/ionic/components/nav/nav-item.js +++ b/ionic/components/nav/nav-item.js @@ -1,127 +1,40 @@ -import { - Component, - DynamicComponent, - Decorator, - Ancestor, - NgElement, - DynamicComponentLoader, - ElementRef, - Query, - View, -} from 'angular2/angular2'; +import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref'; -import { - Injectable, - bind, - Optional, -} from 'angular2/di'; - -import {Toolbar} from 'ionic/components/toolbar/toolbar'; -import {NavInjectable} from 'ionic/components/nav/nav'; import * as util from 'ionic/util'; -/* - * NavController is the public interface for pushing, popping, etc that is injected - * by users. - * Each nav item exposes a new NavController. - */ -export class NavController { - constructor() { - // Contains data passed to this NavController's NavItem - this.params = {}; - // this.navItem and this.nav are set by NavItem below. - } - addToolbar(placement: String, toolbar: Toolbar) { - this.navItem._toolbars[placement].push(toolbar); - } - - removeToolbar(placement: String, toolbar: Toolbar) { - let bars = this.navItem._toolbars[placement]; - bars && util.array.remove(bars, toolbar); - } - - push() { - return this.nav.push.apply(this.nav, arguments); - } - pop() { - return this.nav.pop.apply(this.nav, arguments); - } -} - -@Component({ - selector: '.nav-item', - properties: { - _item: 'item' - }, - injectables: [ - // Allow all descendants to inject NavController and do nav operations. - NavController - ] -}) -@View({ - // See below for this. - template: '', - directives: [NavItemDynamicComponent] -}) export class NavItem { - constructor( - // TODO for now, we can't inject tab as if it's a Nav - navInjectable: NavInjectable, - navCtrl: NavController, - element: NgElement - ) { - this.domElement = element.domElement; - this._toolbars = { - top: [], - bottom: [] - }; - this.navCtrl = navCtrl; - navCtrl.nav = navInjectable.nav; - navCtrl.navItem = this; + + constructor(nav, ComponentClass, params = {}) { + this.nav = nav; + this.Class = ComponentClass; + this.params = params; + this.id = util.nextUid(); } - set _item(data) { - var navChild = this.dynamicComponentChild; + setup() { + let resolve; + let promise = new Promise((res) => { resolve = res; }); - if (this.initialized) return; - this.initialized = true; + let injector = null; - this.Class = data.Class; - util.extend(this.navCtrl.params, data.params || {}); + this.nav.loader.loadIntoExistingLocation(this.Class, this.nav.itemContent.elementRef, injector) + .then((componentRef) => { - navChild._loader.loadIntoExistingLocation(this.Class, navChild._elementRef).then((instance) => { - this.instance = instance; - data.finishSetup(this, instance); + console.log('Component loadIntoExistingLocation completed') + + resolve(); }); - } -} -/** - * In angular 2.0.0-alpha.21, DynamicComponents are not allowed to publish injectables - * (bug, see https://github.com/angular/angular/issues/1596). - * To fix this problem, we have the `NavItem` above publish a `NavController ` injectable - * so the rest of the app has access to nav operations. Then we have a DynamicComponent - * instantiate the user's page. - * The `NavItem` class above can be turned into a DynamicComponent and this class can be removed - * once injectables are allowed on regular Components. - */ -@DynamicComponent({ - selector: '.nav-item-child', - properties: { - _item: 'item' - } -}) -export class NavItemDynamicComponent { - constructor( - loader: DynamicComponentLoader, - elementRef: ElementRef, - @Ancestor() navItem: NavItem - ) { - this._loader = loader; - this._elementRef = elementRef; - navItem.dynamicComponentChild = this; + // let vc = new ViewContainerRef(this.nav.viewManager, this.nav.elementRef); + + // debugger + // let view = vc.create(this.Class, -1, this.nav.itemContent.elementRef, injector); + + + return promise; } + } diff --git a/ionic/components/nav/nav.js b/ionic/components/nav/nav.js index 51894f8980..fe22d37b03 100644 --- a/ionic/components/nav/nav.js +++ b/ionic/components/nav/nav.js @@ -1,58 +1,76 @@ -import { - Component, - View, - If, - For, - NgElement, - Query, - QueryList, - Descendants -} from 'angular2/angular2'; +import {Parent, Ancestor} from 'angular2/src/core/annotations_impl/visibility'; +import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations'; +import {View} from 'angular2/src/core/annotations_impl/view'; +import {DynamicComponentLoader} from 'angular2/src/core/compiler/dynamic_component_loader'; +import {ElementRef} from 'angular2/src/core/compiler/element_ref'; + import {NavBase} from 'ionic/components/nav/nav-base'; import {NavItem, NavItemDynamicComponent} from 'ionic/components/nav/nav-item'; import {ToolbarContainer} from 'ionic/components/toolbar/toolbar'; -/** - * We need a way for children to get ahold of the instantiated `Nav`. - * Until angular supports components adding themselves to the Injector, - * Nav is going to add an instance of a "NavInjectable" class to the injector. - * This NavInjectable will have a pointer to the Nav class on `this.nav`. - * Now descendant components (only our private ones) will have access to NavInjectable, - * and be able to get access to the Nav through `navInjectable.nav` (@see navItem) - */ -export class NavInjectable {} @Component({ selector: 'ion-nav', properties: { initial: 'initial' - }, - injectables: [ - // Add NavInjectable to the injector for this and all descendants - NavInjectable - ] + } }) @View({ template: ` -
-
+
+
-