ionic-angular
Version:
[](https://circleci.com/gh/driftyco/ionic)
120 lines (110 loc) • 4.24 kB
JavaScript
/**
* @ngdoc directive
* @name ionTabs
* @module ionic
* @delegate ionic.service:$ionicTabsDelegate
* @restrict E
* @codepen odqCz
*
* @description
* Powers a multi-tabbed interface with a Tab Bar and a set of "pages" that can be tabbed
* through.
*
* Assign any [tabs class](/docs/components#tabs) to the element to define
* its look and feel.
*
* For iOS, tabs will appear at the bottom of the screen. For Android, tabs will be at the top
* of the screen, below the nav-bar. This follows each OS's design specification, but can be
* configured with the {@link ionic.provider:$ionicConfigProvider}.
*
* See the {@link ionic.directive:ionTab} directive's documentation for more details on
* individual tabs.
*
* Note: do not place ion-tabs inside of an ion-content element; it has been known to cause a
* certain CSS bug.
*
* @usage
* ```html
* <ion-tabs class="tabs-positive tabs-icon-top">
*
* <ion-tab title="Home" icon-on="ion-ios-filing" icon-off="ion-ios-filing-outline">
* <!-- Tab 1 content -->
* </ion-tab>
*
* <ion-tab title="About" icon-on="ion-ios-clock" icon-off="ion-ios-clock-outline">
* <!-- Tab 2 content -->
* </ion-tab>
*
* <ion-tab title="Settings" icon-on="ion-ios-gear" icon-off="ion-ios-gear-outline">
* <!-- Tab 3 content -->
* </ion-tab>
*
* </ion-tabs>
* ```
*
* @param {string=} delegate-handle The handle used to identify these tabs
* with {@link ionic.service:$ionicTabsDelegate}.
*/
IonicModule
.directive('ionTabs', [
'$ionicTabsDelegate',
'$ionicConfig',
function($ionicTabsDelegate, $ionicConfig) {
return {
restrict: 'E',
scope: true,
controller: '$ionicTabs',
compile: function(tElement) {
//We cannot use regular transclude here because it breaks element.data()
//inheritance on compile
var innerElement = jqLite('<div class="tab-nav tabs">');
innerElement.append(tElement.contents());
tElement.append(innerElement)
.addClass('tabs-' + $ionicConfig.tabs.position() + ' tabs-' + $ionicConfig.tabs.style());
return { pre: prelink, post: postLink };
function prelink($scope, $element, $attr, tabsCtrl) {
var deregisterInstance = $ionicTabsDelegate._registerInstance(
tabsCtrl, $attr.delegateHandle, tabsCtrl.hasActiveScope
);
tabsCtrl.$scope = $scope;
tabsCtrl.$element = $element;
tabsCtrl.$tabsElement = jqLite($element[0].querySelector('.tabs'));
$scope.$watch(function() { return $element[0].className; }, function(value) {
var isTabsTop = value.indexOf('tabs-top') !== -1;
var isHidden = value.indexOf('tabs-item-hide') !== -1;
$scope.$hasTabs = !isTabsTop && !isHidden;
$scope.$hasTabsTop = isTabsTop && !isHidden;
$scope.$emit('$ionicTabs.top', $scope.$hasTabsTop);
});
function emitLifecycleEvent(ev, data) {
ev.stopPropagation();
var previousSelectedTab = tabsCtrl.previousSelectedTab();
if (previousSelectedTab) {
previousSelectedTab.$broadcast(ev.name.replace('NavView', 'Tabs'), data);
}
}
$scope.$on('$ionicNavView.beforeLeave', emitLifecycleEvent);
$scope.$on('$ionicNavView.afterLeave', emitLifecycleEvent);
$scope.$on('$ionicNavView.leave', emitLifecycleEvent);
$scope.$on('$destroy', function() {
// variable to inform child tabs that they're all being blown away
// used so that while destorying an individual tab, each one
// doesn't select the next tab as the active one, which causes unnecessary
// loading of tab views when each will eventually all go away anyway
$scope.$tabsDestroy = true;
deregisterInstance();
tabsCtrl.$tabsElement = tabsCtrl.$element = tabsCtrl.$scope = innerElement = null;
delete $scope.$hasTabs;
delete $scope.$hasTabsTop;
});
}
function postLink($scope, $element, $attr, tabsCtrl) {
if (!tabsCtrl.selectedTab()) {
// all the tabs have been added
// but one hasn't been selected yet
tabsCtrl.select(0);
}
}
}
};
}]);