refactor(Tabs): Tabs no longer extends NavController

This commit is contained in:
Adam Bradley
2015-10-11 22:44:18 -05:00
parent 8115f8d340
commit ffc5a5e2ce
5 changed files with 93 additions and 154 deletions

View File

@ -862,22 +862,6 @@ export class NavController extends Ion {
return null;
}
/**
* TODO
* @param {TODO} instance TODO
* @returns {TODO} TODO
*/
getByInstance(instance) {
if (instance) {
for (let i = 0, ii = this._views.length; i < ii; i++) {
if (this._views[i].instance === instance) {
return this._views[i];
}
}
}
return null;
}
/**
* TODO
* @param {TODO} index TODO

View File

@ -1,4 +1,4 @@
import {Directive, Component, Host, ElementRef, Compiler, DynamicComponentLoader, AppViewManager, forwardRef, Injector, NgZone, ViewContainerRef} from 'angular2/angular2';
import {Component, Directive, Host, ElementRef, Compiler, DynamicComponentLoader, AppViewManager, forwardRef, NgZone} from 'angular2/angular2';
import {IonicApp} from '../app/app';
import {IonicConfig} from '../../config/config';
@ -60,8 +60,8 @@ import {Tabs} from './tabs';
],
host: {
'[attr.id]': 'panelId',
'[attr.aria-labelledby]': 'labeledBy',
'[attr.aria-hidden]': 'isNotSelected',
'[attr.aria-labelledby]': 'btnId',
'[class.show-tab]': 'isSelected',
'role': 'tabpanel'
},
template: '<template content-anchor></template><ng-content></ng-content>',
@ -69,13 +69,6 @@ import {Tabs} from './tabs';
})
export class Tab extends NavController {
/**
* TODO
* @param {Tabs} tabs TODO
* @param {ElementRef} elementRef TODO
* @param {Injector} injector TODO
* @param {NgZone} zone TODO
*/
constructor(
@Host() tabs: Tabs,
app: IonicApp,
@ -86,44 +79,18 @@ export class Tab extends NavController {
viewManager: AppViewManager,
zone: NgZone
) {
// A Tab is both a container of many pages, and is a page itself.
// A Tab is one page within it's Host Tabs (which also extends NavController)
// A Tab is a NavController for its child pages
super(tabs, app, config, elementRef, compiler, loader, viewManager, zone);
this.tabs = tabs;
let viewCtrl = this.viewCtrl = new ViewController(tabs);
viewCtrl.setInstance(this);
viewCtrl.setContentRef(elementRef);
this._initTab = tabs.addTab(this);
this.getNavbar = viewCtrl.getNavbar = () => {
let activeView = this.getActive();
return activeView && activeView.getNavbar();
};
viewCtrl.enableBack = () => {
// override ViewController's enableBack(), should use the
// active child nav item's enableBack() instead
let activeView = this.getActive();
return (activeView && activeView.enableBack());
};
this.panelId = 'tab-panel-' + viewCtrl.id;
this.labeledBy = 'tab-button-' + viewCtrl.id;
this._isInitial = tabs.add(this);
}
onInit() {
console.log('Tab onInit');
console.debug('Tab onInit');
if (this._initTab) {
if (this._isInitial) {
this.tabs.select(this);
} else {
// TODO: OPTIONAL PRELOAD OTHER TABS!
// setTimeout(() => {
// this.load();
// }, 300);
}
}
@ -133,24 +100,14 @@ export class Tab extends NavController {
animate: false,
navbar: false
};
this.push(this.root, null, opts).then(() => {
callback && callback();
});
this.push(this.root, null, opts).then(callback);
this._loaded = true;
} else {
callback && callback();
callback();
}
}
get isSelected() {
return this.tabs.isActive(this.viewCtrl);
}
get isNotSelected() {
return !this.tabs.isActive(this.viewCtrl);
}
loadContainer(componentType, hostProtoViewRef, viewCtrl, done) {
this.loadNextToAnchor(componentType, this.contentAnchorRef, viewCtrl).then(componentRef => {

View File

@ -37,7 +37,7 @@ ion-tab {
flex-direction: column;
display: none;
&.show-view {
&.show-tab {
display: flex;
}
}
@ -46,6 +46,10 @@ ion-tabs > ion-navbar-section {
order: $flex-order-tab-bar-navbar;
}
ion-tabs ion-navbar.toolbar.deselected-tab {
display: none;
}
ion-tab-bar-section {
position: relative;
order: $flex-order-tab-bar-bottom;

View File

@ -1,13 +1,11 @@
import {Component, Directive, Injector, ElementRef, Compiler, DynamicComponentLoader, AppViewManager, NgZone, Optional, Host, NgFor, forwardRef, ViewContainerRef} from 'angular2/angular2';
import {Directive, ElementRef, Optional, Host, NgFor, forwardRef, ViewContainerRef} from 'angular2/angular2';
import {Ion} from '../ion';
import {IonicApp} from '../app/app';
import {IonicConfig} from '../../config/config';
import {NavController} from '../nav/nav-controller';
import {ViewController} from '../nav/view-controller';
import {ConfigComponent} from '../../config/decorators';
import {Icon} from '../icon/icon';
import * as dom from 'ionic/util/dom';
/**
@ -72,7 +70,7 @@ import * as dom from 'ionic/util/dom';
'</ion-navbar-section>' +
'<ion-tab-bar-section>' +
'<tab-bar role="tablist">' +
'<a *ng-for="#t of tabs" [tab]="t" class="tab-button" role="tab">' +
'<a *ng-for="#t of _tabs" [tab]="t" class="tab-button" role="tab">' +
'<icon [name]="t.tabIcon" [is-active]="t.isSelected" class="tab-button-icon"></icon>' +
'<span class="tab-button-text">{{t.tabTitle}}</span>' +
'</a>' +
@ -90,71 +88,50 @@ import * as dom from 'ionic/util/dom';
forwardRef(() => TabNavBarAnchor)
]
})
export class Tabs extends NavController {
export class Tabs extends Ion {
/**
* TODO
* Hi, I'm "Tabs". I'm really just another Page, with a few special features.
* "Tabs" can be a sibling to other pages that can be navigated to, which those
* sibling pages may or may not have their own tab bars (doesn't matter). The fact
* that "Tabs" can happen to have children "Tab" classes, and each "Tab" can have
* children pages with their own "ViewController" instance, as nothing to do with the
* point that "Tabs" is itself is just a page with its own instance of ViewController.
*/
constructor(
@Optional() hostNavCtrl: NavController,
@Optional() viewCtrl: ViewController,
app: IonicApp,
config: IonicConfig,
elementRef: ElementRef,
compiler: Compiler,
loader: DynamicComponentLoader,
viewManager: AppViewManager,
zone: NgZone
@Optional() viewCtrl: ViewController
) {
super(hostNavCtrl, app, config, elementRef, compiler, loader, viewManager, zone);
super(elementRef, config);
this.app = app;
this._ready = new Promise(res => { this._isReady = res; });
// collection of children "Tab" instances, which extends NavController
this._tabs = [];
// Tabs may also be an actual ViewController which was navigated to
// if Tabs is static and not navigated to within a NavController
// then skip this and don't treat it as it's own ViewController
if (viewCtrl) {
this.viewCtrl = viewCtrl;
// special overrides for the Tabs ViewController
// the Tabs ViewController does not have it's own navbar
// so find the navbar it should use within it's active Tab
viewCtrl.getNavbar = () => {
let activeTab = this.getActive();
if (activeTab && activeTab.instance) {
return activeTab.instance.getNavbar();
}
};
viewCtrl.contentRef = () => {
let activeTab = this.getActive();
if (activeTab && activeTab.instance) {
return activeTab.instance.viewCtrl.contentRef();
}
};
// a Tabs ViewController should not have a back button
// enableBack back button will later be determined
// by the active ViewController that has a navbar
viewCtrl.enableBack = () => {
return false;
};
this._ready = new Promise(res => { this._isReady = res; });
viewCtrl.onReady = () => {
return this._ready;
};
}
}
/**
* @private
* TODO
*/
addTab(tab) {
this._add(tab.viewCtrl);
add(tab) {
tab.id = ++_tabIds;
tab.btnId = 'tab-' + tab.id;
tab.panelId = 'tabpanel-' + tab.id;
this._tabs.push(tab);
// return true/false if it's the initial tab
return (this.length() === 1);
return (this._tabs.length === 1);
}
/**
@ -162,42 +139,66 @@ export class Tabs extends NavController {
* @param {Tab} tab TODO
* @returns {TODO} TODO
*/
select(tab) {
let enteringView = null;
if (typeof tab === 'number') {
enteringView = this.getByIndex(tab);
select(tabOrIndex) {
let selectedTab = null;
if (typeof tabOrIndex === 'number') {
selectedTab = this.getByIndex(tabOrIndex);
} else {
enteringView = this.getByInstance(tab)
selectedTab = tabOrIndex;
}
// If we select the same tab as the active one, do some magic.
if(enteringView === this.getActive()) {
this._touchActive(tab);
return;
}
if (!enteringView || !enteringView.instance || !this.app.isEnabled()) {
if (!selectedTab || !this.app.isEnabled()) {
return Promise.reject();
}
return new Promise(resolve => {
enteringView.instance.load(() => {
let opts = {
animate: false
};
let deselectedTab = this.getSelected();
let leavingView = this.getActive() || new ViewController();
leavingView.shouldDestroy = false;
leavingView.shouldCache = true;
if (selectedTab === deselectedTab) {
// no change
return this._touchActive(selectedTab);
}
this.transition(enteringView, leavingView, opts, () => {
this.highlight && this.highlight.select(tab);
this._isReady();
resolve();
console.debug('select tab', selectedTab.id);
selectedTab.load(() => {
this._isReady && this._isReady();
});
this._tabs.forEach(tab => {
tab.isSelected = (tab === selectedTab);
tab._views.forEach(viewCtrl => {
let navbarRef = viewCtrl.navbarRef();
if (navbarRef) {
navbarRef.nativeElement.classList[tab.isSelected ? 'remove': 'add']('deselected-tab');
}
});
});
});
this.highlight && this.highlight.select(selectedTab);
}
/**
* TODO
* @param {TODO} index TODO
* @returns {TODO} TODO
*/
getByIndex(index) {
if (index < this._tabs.length && index > -1) {
return this._tabs[index];
}
return null;
}
getSelected() {
for (let i = 0; i < this._tabs.length; i++) {
if (this._tabs[i].isSelected) {
return this._tabs[i];
}
}
return null;
}
/**
@ -210,20 +211,17 @@ export class Tabs extends NavController {
if(stateLen > 1) {
// Pop to the root view
tab.popToRoot();
}
return tab.popToRoot();
}
/**
* TODO
* @return TODO
*/
get tabs() {
return this.instances();
return Promise.resolve();
}
}
let _tabIds = -1;
/**
* @private
* TODO
@ -232,8 +230,8 @@ export class Tabs extends NavController {
selector: '.tab-button',
inputs: ['tab'],
host: {
'[attr.id]': 'btnId',
'[attr.aria-controls]': 'panelId',
'[attr.id]': 'tab.btnId',
'[attr.aria-controls]': 'tab.panelId',
'[attr.aria-selected]': 'tab.isSelected',
'[class.has-title]': 'hasTitle',
'[class.has-icon]': 'hasIcon',
@ -254,10 +252,6 @@ class TabButton extends Ion {
onInit() {
this.tab.btn = this;
let id = this.tab.viewCtrl.id;
this.btnId = 'tab-button-' + id;
this.panelId = 'tab-panel-' + id;
this.hasTitle = !!this.tab.tabTitle;
this.hasIcon = !!this.tab.tabIcon;
this.hasTitleOnly = (this.hasTitle && !this.hasIcon);

View File

@ -104,7 +104,7 @@ class IOSTransition extends Animation {
this.add(leavingContent);
leavingContent
.before.addClass(SHOW_VIEW_CSS)
.before.setStyles({ zIndex: leavingView.index })
.before.setStyles({ zIndex: leavingView.index });
if (backDirection) {
leavingContent