diff --git a/ionic/components/app/structure.scss b/ionic/components/app/structure.scss index b7f61e98f5..ec12bdc77a 100644 --- a/ionic/components/app/structure.scss +++ b/ionic/components/app/structure.scss @@ -31,8 +31,9 @@ $flex-order-view-content: 0; $flex-order-toolbar-top: -10; $flex-order-toolbar-bottom: 10; -$flex-order-tab-bar-top: -30; -$flex-order-tab-bar-bottom: 30; +$flex-order-tab-bar-navbar: -30; +$flex-order-tab-bar-top: -20; +$flex-order-tab-bar-bottom: 20; @@ -96,7 +97,8 @@ ion-nav { height: 100%; } -ion-pane { +ion-pane, +ion-view.pane-view { position: absolute; top: 0; right: 0; @@ -110,14 +112,28 @@ ion-pane { flex-direction: column; } -.nav-item { +ion-view { display: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + flex-direction: column; + + background-color: $background-color; + + transform: translateZ(0px); &.show-view { display: flex; } } +.no-navbar > .navbar-container { + display: none; +} + .navbar-container { position: relative; min-height: 4.4rem; @@ -131,20 +147,6 @@ ion-pane { order: $flex-order-view-content; } -ion-view { - display: flex; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - flex-direction: column; - - background-color: $background-color; - - transform: translateZ(0px); -} - [hidden], template, root-anchor { diff --git a/ionic/components/nav-bar/nav-bar.ts b/ionic/components/nav-bar/nav-bar.ts index 1cd3aad2d7..66d7ebed15 100644 --- a/ionic/components/nav-bar/nav-bar.ts +++ b/ionic/components/nav-bar/nav-bar.ts @@ -123,6 +123,6 @@ export class NavbarTemplate { @Optional() viewCtrl: ViewController, @Optional() templateRef: TemplateRef ) { - viewCtrl && viewCtrl.addTemplateRef('navbar', templateRef); + viewCtrl && viewCtrl.setNavbarTemplateRef(templateRef); } } diff --git a/ionic/components/nav/anchors.ts b/ionic/components/nav/anchors.ts deleted file mode 100644 index 64bb3cf6b6..0000000000 --- a/ionic/components/nav/anchors.ts +++ /dev/null @@ -1,53 +0,0 @@ -import {Component, View, Directive, Host, ElementRef, forwardRef, Inject} from 'angular2/angular2'; -import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref'; - -import {Pane} from './pane'; -import {NavController} from './nav-controller'; - - -@Directive({selector: 'template[pane-anchor]'}) -export class PaneAnchor { - constructor( - @Host() @Inject(forwardRef(() => Pane)) pane: Pane, - elementRef: ElementRef - ) { - pane.sectionAnchorElementRef = elementRef; - } -} - - -@Directive({selector: 'template[content-anchor]'}) -export class PaneContentAnchor { - constructor( - @Host() @Inject(forwardRef(() => Pane)) pane: Pane, - viewContainerRef: ViewContainerRef - ) { - pane.contentContainerRef = viewContainerRef; - } -} - - -@Directive({ - selector: 'template[navbar-anchor]' -}) -class NavBarAnchor { - constructor( - @Inject(forwardRef(() => NavController)) navCtrl: NavController, - viewContainerRef: ViewContainerRef - ) { - navCtrl.navbarViewContainer(viewContainerRef); - } -} - - -@Component({ - selector: 'section', - host: { - 'class': 'navbar-container' - } -}) -@View({ - template: '', - directives: [NavBarAnchor] -}) -export class NavBarContainer {} diff --git a/ionic/components/nav/nav-controller.ts b/ionic/components/nav/nav-controller.ts index 83a88b6a3a..3cbdc10a44 100644 --- a/ionic/components/nav/nav-controller.ts +++ b/ionic/components/nav/nav-controller.ts @@ -1,12 +1,12 @@ -import {Compiler, ElementRef, Injector, bind, NgZone} from 'angular2/angular2'; +import {Component, ComponentRef, Compiler, ElementRef, Injector, bind, NgZone} from 'angular2/angular2'; import {DynamicComponentLoader} from 'angular2/src/core/compiler/dynamic_component_loader'; +import {DirectiveBinding} from 'angular2/src/core/compiler/element_injector'; import {AppViewManager} from 'angular2/src/core/compiler/view_manager'; import {Ion} from '../ion'; import {IonicConfig} from '../../config/config'; import {IonicApp} from '../app/app'; import {ViewController} from './view-controller'; -import {PaneController} from './pane'; import {Transition} from '../../transitions/transition'; import {SwipeBackGesture} from './swipe-back'; import * as util from 'ionic/util'; @@ -35,7 +35,6 @@ export class NavController extends Ion { this.zone = zone; this.views = []; - this.panes = new PaneController(this); this._sbTrans = null; this._sbEnabled = config.setting('swipeBackEnabled') || false; @@ -43,7 +42,6 @@ export class NavController extends Ion { this.id = ++ctrlIds; this._ids = -1; - this.zIndexes = -1; // build a new injector for child ViewControllers to use this.bindings = Injector.resolve([ @@ -336,6 +334,51 @@ export class NavController extends Ion { } + compileView(componentType) { + // create a new ion-view annotation + let annotation = new Component({ + selector: 'ion-view', + host: { + '[class.pane-view]': '_paneView' + } + }); + + let ionViewComponentType = DirectiveBinding.createFromType(componentType, annotation); + + // create a unique token that works as a cache key + ionViewComponentType.token = 'ionView' + componentType.name; + + // compile the Component + return this.compiler.compileInHost(ionViewComponentType); + } + + createViewComponetRef(hostProtoViewRef, contentContainerRef, viewCtrlBindings) { + let bindings = this.bindings.concat(Injector.resolve(viewCtrlBindings)); + + // the same guts as DynamicComponentLoader.loadNextToLocation + var hostViewRef = + contentContainerRef.createHostView(hostProtoViewRef, -1, bindings); + var newLocation = this.viewMngr.getHostElement(hostViewRef); + var newComponent = this.viewMngr.getComponent(newLocation); + + var dispose = () => { + var index = contentContainerRef.indexOf(hostViewRef); + if (index !== -1) { + contentContainerRef.remove(index); + } + }; + + return new ComponentRef(newLocation, newComponent, dispose); + } + + getBindings(viewCtrl) { + // create bindings to this ViewController and its NavParams + return this.bindings.concat(Injector.resolve([ + bind(ViewController).toValue(viewCtrl), + bind(NavParams).toValue(viewCtrl.params), + ])); + } + /** * TODO */ @@ -667,28 +710,6 @@ export class NavController extends Ion { return this._anchorER; } - /** - * TODO - * @returns {TODO} TODO - */ - anchorViewContainerRef() { - if (arguments.length) { - this._anchorVC = arguments[0]; - } - return this._anchorVC; - } - - /** - * TODO - * @returns {TODO} TODO - */ - childNavbar() { - if (arguments.length) { - this._childNavbar = arguments[0]; - } - return this._childNavbar; - } - /** * TODO * @param {TODO} view TODO diff --git a/ionic/components/nav/nav.ts b/ionic/components/nav/nav.ts index 3f642b15a2..c0f95f8e12 100644 --- a/ionic/components/nav/nav.ts +++ b/ionic/components/nav/nav.ts @@ -1,4 +1,5 @@ -import {Directive, View, ElementRef, Host, Optional, forwardRef, Injector, NgZone} from 'angular2/angular2'; +import {Component, Directive, View, ElementRef, Host, Optional, forwardRef, Inject, Injector, NgZone, Renderer} from 'angular2/angular2'; +import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref'; import {IonicComponent} from '../../config/decorators'; import {NavController} from './nav-controller'; @@ -23,18 +24,19 @@ export class Nav extends NavController { /** * TODO - * @param {NavController} hostnavCtrl TODO + * @param {NavController} hostNavCtrl TODO * @param {Injector} injector TODO * @param {ElementRef} elementRef TODO * @param {NgZone} zone TODO */ constructor( - @Optional() hostnavCtrl: NavController, + @Optional() hostNavCtrl: NavController, injector: Injector, elementRef: ElementRef, zone: NgZone ) { - super(hostnavCtrl, injector, elementRef, zone); + super(hostNavCtrl, injector, elementRef, zone); + this.panes = []; } /** @@ -55,8 +57,151 @@ export class Nav extends NavController { this.isSwipeBackEnabled( isSwipeBackEnabled ); } + loadContainer(hostProtoViewRef, componentType, viewCtrl, done) { + // this gets or creates the Pane which similar nav items live in + // Nav items with just a navbar/content would all use the same Pane + // Tabs and view's without a navbar would get a different Panes + let structure = this.inspectStructure(hostProtoViewRef); + + if (structure.tabs) { + // the component being loaded is an + // Tabs is essentially a pane, cuz it has its own navbar and content containers + let contentContainerRef = this.viewMngr.getViewContainer(this.anchorElementRef()); + let viewComponetRef = this.createViewComponetRef(hostProtoViewRef, contentContainerRef, this.getBindings(viewCtrl)); + viewComponetRef.instance._paneView = true; + + viewCtrl.disposals.push(() => { + viewComponetRef.dispose(); + }); + + viewCtrl.onReady().then(() => { + done(); + }); + + } else { + // normal ion-view going into pane + this.getPane(structure, viewCtrl, (pane) => { + // add the content of the view into the pane's content area + let viewComponetRef = this.createViewComponetRef(hostProtoViewRef, pane.contentContainerRef, this.getBindings(viewCtrl)); + viewCtrl.disposals.push(() => { + viewComponetRef.dispose(); + + // remove the pane if there are no view items left + pane.totalViews--; + if (pane.totalViews === 0) { + pane.dispose && pane.dispose(); + } + }); + + // count how many ViewControllers are in this pane + pane.totalViews++; + + // a new ComponentRef has been created + // set the ComponentRef's instance to this ViewController + viewCtrl.setInstance(viewComponetRef.instance); + + // remember the ElementRef to the content that was just created + viewCtrl.viewElementRef(viewComponetRef.location); + + // get the NavController's container for navbars, which is + // the place this NavController will add each ViewController's navbar + let navbarContainerRef = pane.navbarContainerRef; + + // get this ViewController's navbar TemplateRef, which may not + // exist if the ViewController's template didn't have an + let navbarTemplateRef = viewCtrl.getNavbarTemplateRef(); + + // create the navbar view if the pane has a navbar container, and the + // ViewController's instance has a navbar TemplateRef to go to inside of it + if (navbarContainerRef && navbarTemplateRef) { + let navbarView = navbarContainerRef.createEmbeddedView(navbarTemplateRef, -1); + + viewCtrl.disposals.push(() => { + let index = navbarContainerRef.indexOf(navbarView); + if (index > -1) { + navbarContainerRef.remove(index); + } + }); + } + + done(); + }); + } + } + + getPane(structure, viewCtrl, done) { + let pane = this.panes[this.panes.length - 1]; + + if (pane && pane.navbar === structure.navbar) { + // the last pane's structure is the same as the one + // this ViewController will need, so reuse it + done(pane); + + } else { + // create a new nav pane + this.loader.loadNextToLocation(Pane, this.anchorElementRef(), this.getBindings(viewCtrl)).then(componentRef => { + + // get the pane reference + pane = this.newPane; + this.newPane = null; + + pane.showNavbar(structure.navbar); + pane.dispose = () => { + componentRef.dispose(); + this.panes.splice(this.panes.indexOf(pane), 1); + }; + + this.panes.push(pane); + + done(pane); + + }, loaderErr => { + console.error(loaderErr); + + }).catch(err => { + console.error(err); + }); + + } + } + + addPane(pane) { + this.newPane = pane; + } + + inspectStructure(componentProtoViewRef) { + let navbar = false; + let tabs = false; + //let key = '_'; + + componentProtoViewRef._protoView.elementBinders.forEach(rootElementBinder => { + if (!rootElementBinder.componentDirective || !rootElementBinder.nestedProtoView) return; + + rootElementBinder.nestedProtoView.elementBinders.forEach(nestedElementBinder => { + if ( isComponent(nestedElementBinder, 'Tabs') ) { + tabs = true; + } + if (!nestedElementBinder.componentDirective && nestedElementBinder.nestedProtoView) { + nestedElementBinder.nestedProtoView.elementBinders.forEach(templatedElementBinder => { + if ( isComponent(templatedElementBinder, 'Navbar') ) { + navbar = true; + } + }); + } + }); + }); + + return { + navbar, + tabs + }; + } + } +function isComponent(elementBinder, id) { + return (elementBinder && elementBinder.componentDirective && elementBinder.componentDirective.metadata.id == id); +} @Directive({selector: 'template[pane-anchor]'}) class NavPaneAnchor { @@ -64,3 +209,66 @@ class NavPaneAnchor { nav.anchorElementRef(elementRef); } } + + +@Directive({selector: 'template[navbar-anchor]'}) +class NavBarAnchor { + constructor( + @Host() @Inject(forwardRef(() => Pane)) pane: Pane, + viewContainerRef: ViewContainerRef + ) { + pane.navbarContainerRef = viewContainerRef; + } +} + + +@Directive({selector: 'template[content-anchor]'}) +class ContentAnchor { + constructor( + @Host() @Inject(forwardRef(() => Pane)) pane: Pane, + viewContainerRef: ViewContainerRef + ) { + pane.contentContainerRef = viewContainerRef; + } +} + + +@Component({ + selector: 'ion-pane', + host: { + 'class': 'nav' + } +}) +@View({ + template: '' + + '' + + '
' + + '' + + '
', + directives: [NavBarAnchor, ContentAnchor] +}) +class Pane { + constructor( + nav: Nav, + elementRef: ElementRef, + renderer: Renderer + ) { + this.zIndex = (nav.panes.length ? nav.panes[nav.panes.length - 1].zIndex + 1 : 0); + renderer.setElementStyle(elementRef, 'zIndex', this.zIndex); + + nav.addPane(this); + this.totalViews = 0; + this.elementRef = elementRef; + this.renderer = renderer; + } + + showNavbar(hasNavbar) { + this.hasNavbar = hasNavbar; + if (!hasNavbar) { + this.renderer.setElementClass(this.elementRef, 'no-navbar', true); + } + } + +} diff --git a/ionic/components/nav/pane.ts b/ionic/components/nav/pane.ts deleted file mode 100644 index 312aa63872..0000000000 --- a/ionic/components/nav/pane.ts +++ /dev/null @@ -1,134 +0,0 @@ -import {Component, Directive, View, ElementRef, Inject, forwardRef, Injector, bind} from 'angular2/angular2'; - -import {Ion} from '../ion'; -import {IonicConfig} from '../../config/config'; -import {NavController} from './nav-controller'; -import {IonicComponent} from '../../config/decorators'; -import {PaneAnchor, PaneContentAnchor, NavBarContainer} from './anchors'; - -/** - * TODO - */ -export class PaneController { - /** - * TODO - * @param {NavController} navCtrl TODO - */ - constructor(navCtrl: NavController) { - this.panes = []; - this.navCtrl = navCtrl; - - this.bindings = Injector.resolve([ - bind(NavController).toValue(navCtrl) - ]); - } - - /** - * TODO - * @param {TODO} nav TODO - * @param {Function} nav TODO - */ - get(itemStructure, callback) { - // this gets or creates the Pane which similar nav items live in - // Nav items with just a navbar/content would all use the same Pane - // Tabs and view's without a navbar would get a different Panes - - let key = itemStructure.key; - let navCtrl = this.navCtrl; - let pane = this.panes[this.panes.length - 1]; - - if (pane && pane.key === key) { - // the last pane's structure is the same as the one the item needs to go in - callback(pane); - - } else { - // create a new nav pane - navCtrl.loader.loadNextToLocation(Pane, navCtrl.anchorElementRef(), this.bindings).then((componentRef) => { - - // get the pane reference - pane = this.newPane; - this.newPane = null; - - let sectionAnchorElementRef = pane && pane.sectionAnchorElementRef; - if (!sectionAnchorElementRef) { - return callback(); - } - - pane.key = key; - pane.dispose = () => { - componentRef.dispose(); - this.panes.splice(this.panes.indexOf(pane), 1); - }; - - this.panes.push(pane); - - let promises = []; - let sectionsToAdd = []; - - // decide which sections should be added to this Pane, ie: nav bars, footers, etc. - // add only the sections it needs - if (itemStructure.navbar) { - sectionsToAdd.push(NavBarContainer); - } - - // add the sections which this type of Pane requires - sectionsToAdd.forEach(SectionClass => { - // as each section is compiled and added to the Pane - // the section will add a reference to itself in the Pane's sections object - promises.push( - navCtrl.loader.loadNextToLocation(SectionClass, sectionAnchorElementRef) - ); - }); - - // wait for all of the sections to resolve - Promise.all(promises).then(() => { - callback(pane); - }, err => { - console.error(err) - }); - - }, loaderErr => { - console.error(loaderErr); - - }).catch(err => { - console.error(err); - }); - - } - } - - add(pane) { - this.newPane = pane; - } - -} - -@IonicComponent({ - selector: 'ion-pane', - classId: 'nav', - host: { - '[style.z-index]': 'zIndex', - } -}) -@View({ - template: ` - -
- -
- `, - directives: [PaneAnchor, PaneContentAnchor] -}) -export class Pane extends Ion { - constructor( - @Inject(forwardRef(() => NavController)) navCtrl: NavController, - elementRef: ElementRef, - ionicConfig: IonicConfig - ) { - super(elementRef, ionicConfig); - navCtrl.panes.add(this); - this.totalItems = 0; - this.zIndex = ++navCtrl.zIndexes; - } - -} diff --git a/ionic/components/nav/view-controller.ts b/ionic/components/nav/view-controller.ts index ea13d2cd2d..3a1a900165 100644 --- a/ionic/components/nav/view-controller.ts +++ b/ionic/components/nav/view-controller.ts @@ -1,8 +1,6 @@ -import {Component, EventEmitter, ElementRef, bind, Injector, ComponentRef} from 'angular2/angular2'; -import {DirectiveBinding} from 'angular2/src/core/compiler/element_injector'; - import {NavParams} from './nav-controller'; + /** * TODO */ @@ -16,188 +14,42 @@ export class ViewController { this.state = 0; this.disposals = []; - this.protos = {}; this._nbItms = []; - this._promises = []; - this.templateRefs = {}; + this.navbarTemplateRef = null; } /** - * TODO - * @param {TODO} name TODO - * @param {TODO} protoViewRef TODO + * @private */ - addProtoViewRef(name, protoViewRef) { - this.protos[name] = protoViewRef; - } - - /** - * TODO - * @param {TODO} name TODO - * @param {TODO} templateRef TODO - */ - addTemplateRef(name, templateRef) { - this.templateRefs[name] = templateRef; - } - - /** - * TODO - * @param {Function} callback TODO - * @returns {TODO} TODO - */ - stage(callback) { + stage(done) { let navCtrl = this.navCtrl; if (this.instance || !navCtrl) { // already compiled this view - return callback(); + return done(); } - let annotation = new Component({ - selector: 'ion-view', - host: { - 'class': 'nav-item' - } - }); + // compile the componenet and create a ProtoViewRef + navCtrl.compileView(this.componentType).then(hostProtoViewRef => { - let ionViewComponentType = DirectiveBinding.createFromType(this.componentType, annotation); + // get the pane the NavController wants to use + // the pane is where all this content will be placed into + navCtrl.loadContainer(hostProtoViewRef, this.componentType, this, () => { - // create a unique token that works as a cache key - ionViewComponentType.token = 'ionView' + this.componentType.name; - - // compile the Component - navCtrl.compiler.compileInHost(ionViewComponentType).then(hostProtoViewRef => { - - // figure out the sturcture of this Component - // does it have a navbar? Is it tabs? Should it not have a navbar or any toolbars? - let itemStructure = this.sturcture = this.inspectStructure(hostProtoViewRef); - - // get the appropriate Pane which this ViewController will fit into - navCtrl.panes.get(itemStructure, pane => { - this.pane = pane; - - let bindings = navCtrl.bindings.concat(Injector.resolve([ - bind(NavParams).toValue(this.params), - bind(ViewController).toValue(this) - ])); - - // add the content of the view to the content area - // it will already have the correct context - let contentContainer = pane.contentContainerRef; - - // the same guts as DynamicComponentLoader.loadNextToLocation - var hostViewRef = - contentContainer.createHostView(hostProtoViewRef, -1, bindings); - var newLocation = navCtrl.viewMngr.getHostElement(hostViewRef); - var newComponent = navCtrl.viewMngr.getComponent(newLocation); - pane.totalItems++; - - var dispose = () => { - var index = contentContainer.indexOf(hostViewRef); - if (index !== -1) { - contentContainer.remove(index); - - // remove the pane if there are no view items left - pane.totalItems--; - if (pane.totalItems === 0) { - pane.dispose(); - } - } - }; - this.disposals.push(dispose); - var viewComponetRef = new ComponentRef(newLocation, newComponent, dispose); - - // get the component's instance, and set it to the this ViewController - this.setInstance(viewComponetRef.instance); - this.viewElementRef(viewComponetRef.location); - - // // get the item container's nav bar - let navbarViewContainer = navCtrl.navbarViewContainer(); - - // // get the item's navbar protoview - let navbarTemplateRef = this.templateRefs.navbar; - - // add a navbar view if the pane has a navbar container, and the - // item's instance has a navbar protoview to go to inside of it - if (navbarViewContainer && navbarTemplateRef) { - let navbarView = navbarViewContainer.createEmbeddedView(navbarTemplateRef, -1); - - this.disposals.push(() => { - let index = navbarViewContainer.indexOf(navbarView); - if (index > -1) { - navbarViewContainer.remove(index); - } - }); - } - - // this item has finished loading + // this ViewController instance has finished loading try { this.loaded(); } catch (e) { console.error(e); } - // fire callback when all child promises have been resolved - Promise.all(this._promises).then(() => { - callback(); - this._promises = []; - }); - - }, panesErr => { - console.error(panesErr); + done(); }); - }, compileInHostErr => { - console.error(compileInHostErr); }); } - /** - * TODO - * @param {TODO} childPromise TODO - */ - addPromise(childPromise) { - this._promises.push(childPromise); - } - - /** - * TODO - * @param {TODO} componentProtoViewRef TODO - */ - inspectStructure(componentProtoViewRef) { - let navbar = false; - let key = '_'; - - componentProtoViewRef._protoView.elementBinders.forEach(rootElementBinder => { - if (!rootElementBinder.componentDirective || !rootElementBinder.nestedProtoView) return; - - rootElementBinder.nestedProtoView.elementBinders.forEach(nestedElementBinder => { - if ( isComponent(nestedElementBinder, 'Tabs') ) { - navbar = true; - } - if (!nestedElementBinder.componentDirective && nestedElementBinder.nestedProtoView) { - nestedElementBinder.nestedProtoView.elementBinders.forEach(templatedElementBinder => { - if ( isComponent(templatedElementBinder, 'Navbar') ) { - navbar = true; - } - }); - } - }); - }); - - if (this.navCtrl.childNavbar()) { - navbar = false; - } - - if (navbar) key += 'n' - - return { - navbar, - key - }; - } - /** * TODO * @returns {boolean} TODO @@ -247,6 +99,20 @@ export class ViewController { } } + /** + * @private + */ + setNavbarTemplateRef(templateRef) { + this.navbarTemplateRef = templateRef; + } + + /** + * @private + */ + getNavbarTemplateRef() { + return this.navbarTemplateRef; + } + /** * TODO * @param {TODO} val TODO @@ -329,7 +195,7 @@ export class ViewController { * TODO * @returns {TODO} TODO */ - navbarBackgroundRef() { + navbarBgRef() { let navbarView = this.navbarView(); if (navbarView) { return navbarView.getNativeElement().querySelector('.toolbar-background'); @@ -406,7 +272,3 @@ export class ViewController { } } - -function isComponent(elementBinder, id) { - return (elementBinder && elementBinder.componentDirective && elementBinder.componentDirective.metadata.id == id); -} diff --git a/ionic/components/tabs/tab.ts b/ionic/components/tabs/tab.ts index 22b29d168d..24afe6c9a9 100644 --- a/ionic/components/tabs/tab.ts +++ b/ionic/components/tabs/tab.ts @@ -1,4 +1,5 @@ import {Directive, Component, View, Host, ElementRef, forwardRef, Injector, NgZone} from 'angular2/angular2'; +import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref'; import {NavController} from '../nav/nav-controller'; import {ViewController} from '../nav/view-controller'; @@ -31,8 +32,8 @@ import {Tabs} from './tabs'; } }) @View({ - template: '', - directives: [forwardRef(() => TabPaneAnchor)] + template: '', + directives: [forwardRef(() => TabContentAnchor)] }) export class Tab extends NavController { @@ -55,12 +56,10 @@ export class Tab extends NavController { super(tabs, injector, elementRef, zone); this.tabs = tabs; - this.childNavbar(true); - let viewCtrl = this.viewCtrl = new ViewController(tabs.Host); viewCtrl.setInstance(this); viewCtrl.viewElementRef(elementRef); - tabs.addTab(this); + this._initTab = tabs.addTab(this); this.navbarView = viewCtrl.navbarView = () => { let activeView = this.getActive(); @@ -79,18 +78,19 @@ export class Tab extends NavController { } onInit() { - if (this._initialResolve) { - this.tabs.select(this).then(() => { - this._initialResolve(); - this._initialResolve = null; - }); + console.log('Tab onInit'); + + if (this._initTab) { + this.tabs.select(this); + + } else { + // TODO: OPTIONAL PRELOAD OTHER TABS! + // setTimeout(() => { + // this.load(); + // }, 300); } } - /** - * TODO - * @param {Function} callback TODO - */ load(callback) { if (!this._loaded && this.root) { let opts = { @@ -107,15 +107,6 @@ export class Tab extends NavController { } } - /** - * TODO - * @returns {TODO} TODO - */ - queueInitial() { - // this Tab will be used as the initial one for the first load of Tabs - return new Promise(res => { this._initialResolve = res; }); - } - get isSelected() { return this.tabs.isActive(this.viewCtrl); } @@ -124,23 +115,53 @@ export class Tab extends NavController { return !this.tabs.isActive(this.viewCtrl); } + loadContainer(hostProtoViewRef, componentType, viewCtrl, done) { + + let viewComponetRef = this.createViewComponetRef(hostProtoViewRef, this.contentContainerRef, this.getBindings(viewCtrl)); + viewCtrl.disposals.push(() => { + viewComponetRef.dispose(); + }); + + // a new ComponentRef has been created + // set the ComponentRef's instance to this ViewController + viewCtrl.setInstance(viewComponetRef.instance); + + // remember the ElementRef to the content that was just created + viewCtrl.viewElementRef(viewComponetRef.location); + + // get the NavController's container for navbars, which is + // the place this NavController will add each ViewController's navbar + let navbarContainerRef = this.tabs.navbarContainerRef; + + // get this ViewController's navbar TemplateRef, which may not + // exist if the ViewController's template didn't have an + let navbarTemplateRef = viewCtrl.getNavbarTemplateRef(); + + // create the navbar view if the pane has a navbar container, and the + // ViewController's instance has a navbar TemplateRef to go to inside of it + if (navbarContainerRef && navbarTemplateRef) { + let navbarView = navbarContainerRef.createEmbeddedView(navbarTemplateRef, -1); + + viewCtrl.disposals.push(() => { + let index = navbarContainerRef.indexOf(navbarView); + if (index > -1) { + navbarContainerRef.remove(index); + } + }); + } + + done(); + } + } -/** - * TODO - */ -@Directive({ - selector: 'template[pane-anchor]' -}) -class TabPaneAnchor { - - /** - * TODO - * @param {Tab} tab TODO - * @param {ElementRef} elementRef TODO - */ - constructor(@Host() tab: Tab, elementRef: ElementRef) { - tab.anchorElementRef(elementRef); +@Directive({selector: 'template[content-anchor]'}) +class TabContentAnchor { + constructor( + @Host() tab: Tab, + viewContainerRef: ViewContainerRef + ) { + tab.contentContainerRef = viewContainerRef; } } diff --git a/ionic/components/tabs/tabs.scss b/ionic/components/tabs/tabs.scss index 49b7761dcd..d211e6852e 100644 --- a/ionic/components/tabs/tabs.scss +++ b/ionic/components/tabs/tabs.scss @@ -42,6 +42,10 @@ ion-tab { } } +ion-tabs > .navbar-container { + order: $flex-order-tab-bar-navbar; +} + .tab-bar-container { position: relative; order: $flex-order-tab-bar-bottom; diff --git a/ionic/components/tabs/tabs.ts b/ionic/components/tabs/tabs.ts index a2ed163e71..f67a1d91b7 100644 --- a/ionic/components/tabs/tabs.ts +++ b/ionic/components/tabs/tabs.ts @@ -1,4 +1,5 @@ import {Component, Directive, View, Injector, NgFor, ElementRef, Optional, Host, forwardRef, NgZone} from 'angular2/angular2'; +import {ViewContainerRef} from 'angular2/src/core/compiler/view_container_ref'; import {Ion} from '../ion'; import {IonicApp} from '../app/app'; @@ -42,6 +43,9 @@ import * as dom from 'ionic/util/dom'; }) @IonicView({ template: '' + + '' + '