ionic-angular
Version:
[](https://circleci.com/gh/driftyco/ionic)
205 lines (181 loc) • 7.52 kB
JavaScript
/**
* @ngdoc directive
* @name ionTab
* @module ionic
* @restrict E
* @parent ionic.directive:ionTabs
*
* @description
* Contains a tab's content. The content only exists while the given tab is selected.
*
* Each ionTab has its own view history.
*
* @usage
* ```html
* <ion-tab
* title="Tab!"
* icon="my-icon"
* href="#/tab/tab-link"
* on-select="onTabSelected()"
* on-deselect="onTabDeselected()">
* </ion-tab>
* ```
* For a complete, working tab bar example, see the {@link ionic.directive:ionTabs} documentation.
*
* @param {string} title The title of the tab.
* @param {string=} href The link that this tab will navigate to when tapped.
* @param {string=} icon The icon of the tab. If given, this will become the default for icon-on and icon-off.
* @param {string=} icon-on The icon of the tab while it is selected.
* @param {string=} icon-off The icon of the tab while it is not selected.
* @param {expression=} badge The badge to put on this tab (usually a number).
* @param {expression=} badge-style The style of badge to put on this tab (eg: badge-positive).
* @param {expression=} on-select Called when this tab is selected.
* @param {expression=} on-deselect Called when this tab is deselected.
* @param {expression=} ng-click By default, the tab will be selected on click. If ngClick is set, it will not. You can explicitly switch tabs using {@link ionic.service:$ionicTabsDelegate#select $ionicTabsDelegate.select()}.
* @param {expression=} hidden Whether the tab is to be hidden or not.
* @param {expression=} disabled Whether the tab is to be disabled or not.
*/
IonicModule
.directive('ionTab', [
'$compile',
'$ionicConfig',
'$ionicBind',
'$ionicViewSwitcher',
function($compile, $ionicConfig, $ionicBind, $ionicViewSwitcher) {
//Returns ' key="value"' if value exists
function attrStr(k, v) {
return isDefined(v) ? ' ' + k + '="' + v + '"' : '';
}
return {
restrict: 'E',
require: ['^ionTabs', 'ionTab'],
controller: '$ionicTab',
scope: true,
compile: function(element, attr) {
//We create the tabNavTemplate in the compile phase so that the
//attributes we pass down won't be interpolated yet - we want
//to pass down the 'raw' versions of the attributes
var tabNavTemplate = '<ion-tab-nav' +
attrStr('ng-click', attr.ngClick) +
attrStr('title', attr.title) +
attrStr('icon', attr.icon) +
attrStr('icon-on', attr.iconOn) +
attrStr('icon-off', attr.iconOff) +
attrStr('badge', attr.badge) +
attrStr('badge-style', attr.badgeStyle) +
attrStr('hidden', attr.hidden) +
attrStr('disabled', attr.disabled) +
attrStr('class', attr['class']) +
'></ion-tab-nav>';
//Remove the contents of the element so we can compile them later, if tab is selected
var tabContentEle = document.createElement('div');
for (var x = 0; x < element[0].children.length; x++) {
tabContentEle.appendChild(element[0].children[x].cloneNode(true));
}
var childElementCount = tabContentEle.childElementCount;
element.empty();
var navViewName, isNavView;
if (childElementCount) {
if (tabContentEle.children[0].tagName === 'ION-NAV-VIEW') {
// get the name if it's a nav-view
navViewName = tabContentEle.children[0].getAttribute('name');
tabContentEle.children[0].classList.add('view-container');
isNavView = true;
}
if (childElementCount === 1) {
// make the 1 child element the primary tab content container
tabContentEle = tabContentEle.children[0];
}
if (!isNavView) tabContentEle.classList.add('pane');
tabContentEle.classList.add('tab-content');
}
return function link($scope, $element, $attr, ctrls) {
var childScope;
var childElement;
var tabsCtrl = ctrls[0];
var tabCtrl = ctrls[1];
var isTabContentAttached = false;
$scope.$tabSelected = false;
$ionicBind($scope, $attr, {
onSelect: '&',
onDeselect: '&',
title: '@',
uiSref: '@',
href: '@'
});
tabsCtrl.add($scope);
$scope.$on('$destroy', function() {
if (!$scope.$tabsDestroy) {
// if the containing ionTabs directive is being destroyed
// then don't bother going through the controllers remove
// method, since remove will reset the active tab as each tab
// is being destroyed, causing unnecessary view loads and transitions
tabsCtrl.remove($scope);
}
tabNavElement.isolateScope().$destroy();
tabNavElement.remove();
tabNavElement = tabContentEle = childElement = null;
});
//Remove title attribute so browser-tooltip does not apear
$element[0].removeAttribute('title');
if (navViewName) {
tabCtrl.navViewName = $scope.navViewName = navViewName;
}
$scope.$on('$stateChangeSuccess', selectIfMatchesState);
selectIfMatchesState();
function selectIfMatchesState() {
if (tabCtrl.tabMatchesState()) {
tabsCtrl.select($scope, false);
}
}
var tabNavElement = jqLite(tabNavTemplate);
tabNavElement.data('$ionTabsController', tabsCtrl);
tabNavElement.data('$ionTabController', tabCtrl);
tabsCtrl.$tabsElement.append($compile(tabNavElement)($scope));
function tabSelected(isSelected) {
if (isSelected && childElementCount) {
// this tab is being selected
// check if the tab is already in the DOM
// only do this if the tab has child elements
if (!isTabContentAttached) {
// tab should be selected and is NOT in the DOM
// create a new scope and append it
childScope = $scope.$new();
childElement = jqLite(tabContentEle);
$ionicViewSwitcher.viewEleIsActive(childElement, true);
tabsCtrl.$element.append(childElement);
$compile(childElement)(childScope);
isTabContentAttached = true;
}
// remove the hide class so the tabs content shows up
$ionicViewSwitcher.viewEleIsActive(childElement, true);
} else if (isTabContentAttached && childElement) {
// this tab should NOT be selected, and it is already in the DOM
if ($ionicConfig.views.maxCache() > 0) {
// keep the tabs in the DOM, only css hide it
$ionicViewSwitcher.viewEleIsActive(childElement, false);
} else {
// do not keep tabs in the DOM
destroyTab();
}
}
}
function destroyTab() {
childScope && childScope.$destroy();
isTabContentAttached && childElement && childElement.remove();
tabContentEle.innerHTML = '';
isTabContentAttached = childScope = childElement = null;
}
$scope.$watch('$tabSelected', tabSelected);
$scope.$on('$ionicView.afterEnter', function() {
$ionicViewSwitcher.viewEleIsActive(childElement, $scope.$tabSelected);
});
$scope.$on('$ionicView.clearCache', function() {
if (!$scope.$tabSelected) {
destroyTab();
}
});
};
}
};
}]);