From ecfdbaa67b076bab61e9573fc650ee6eccb459b1 Mon Sep 17 00:00:00 2001 From: Andy Joslin Date: Sat, 8 Mar 2014 12:52:42 -0700 Subject: [PATCH] fix(ionTabs): do not pre-transclude; stops error on compile Closes #730 --- js/ext/angular/src/directive/ionicTabBar.js | 53 ++++++++++--------- .../test/directive/ionicTabBar.unit.js | 49 +++++++++++------ 2 files changed, 59 insertions(+), 43 deletions(-) diff --git a/js/ext/angular/src/directive/ionicTabBar.js b/js/ext/angular/src/directive/ionicTabBar.js index 14d1eb1e75..17423a64ad 100644 --- a/js/ext/angular/src/directive/ionicTabBar.js +++ b/js/ext/angular/src/directive/ionicTabBar.js @@ -144,7 +144,8 @@ function($scope, $ionicViewService, $rootScope, $element) { }]) // Generic controller directive -.directive('ionTab', ['$rootScope', '$animate', '$ionicBind', '$compile', '$ionicViewService', function($rootScope, $animate, $ionicBind, $compile, $ionicViewService) { +.directive('ionTab', ['$rootScope', '$animate', '$ionicBind', '$compile', '$ionicViewService', +function($rootScope, $animate, $ionicBind, $compile, $ionicViewService) { //Returns ' key="value"' if value exists function attrStr(k,v) { @@ -154,10 +155,17 @@ function($scope, $ionicViewService, $rootScope, $element) { restrict: 'E', require: ['^ionTabs', 'ionTab'], replace: true, - transclude: 'element', controller: '$ionicTab', scope: true, - compile: function(element, attr, transclude) { + compile: function(element, attr) { + //Do we have a navView? + var navView = element[0].querySelector('ion-nav-view') || + element[0].querySelector('data-ion-nav-view'); + var navViewName = navView && navView.getAttribute('name'); + + //Remove the contents of the element so we can compile them later, if tab is selected + var tabContent = angular.element('
') + .append( element.contents().remove() ); return function link($scope, $element, $attr, ctrls) { var childScope, childElement, tabNavElement; tabsCtrl = ctrls[0], @@ -174,6 +182,19 @@ function($scope, $ionicViewService, $rootScope, $element) { href: '@', }); + tabsCtrl.add($scope); + $scope.$on('$destroy', function() { + tabsCtrl.remove($scope); + tabNavElement.isolateScope().$destroy(); + tabNavElement.remove(); + }); + + if (navViewName) { + $scope.navViewName = navViewName; + $scope.$on('$stateChangeSuccess', selectTabIfMatchesState); + selectTabIfMatchesState(); + } + tabNavElement = angular.element( ''+(content||'')+''); $compile(tabsEl)($rootScope.$new()); @@ -256,6 +256,19 @@ describe('tabs', function() { spyOn(tabsCtrl, 'remove'); }); } + + it('should not initially compile content until selected', inject(function($compile, $rootScope) { + var el = $compile('' + + '' + + '
' + + '
')($rootScope); + $rootScope.$apply(); + expect($rootScope.elephant).toBeUndefined(); + el.controller('ionTabs').select(1); + $rootScope.$apply(); + expect($rootScope.elephant).toBe('banana'); + })); + it('should add itself to tabsCtrl and remove on $destroy', function() { var el = setup(); @@ -292,26 +305,28 @@ describe('tabs', function() { expect(tabsCtrl.tabs[0].navViewName).toBeUndefined(); }); - it('should set navViewName and select when necessary if a child nav-view', inject(function($ionicViewService, $rootScope) { - var isCurrent = false; - spyOn($ionicViewService, 'isCurrentStateNavView').andCallFake(function(name) { - return isCurrent; - }); + angular.forEach(['ion-nav-view', 'data-ion-nav-view'], function(directive) { + it('should set navViewName and select when necessary if a child '+directive, inject(function($ionicViewService, $rootScope) { + var isCurrent = false; + spyOn($ionicViewService, 'isCurrentStateNavView').andCallFake(function(name) { + return isCurrent; + }); - setup('', ''); - spyOn(tabsCtrl, 'select'); - var tab = tabsCtrl.tabs[0]; + setup('', '<' + directive + ' name="banana">'); + spyOn(tabsCtrl, 'select'); + var tab = tabsCtrl.tabs[0]; - expect(tab.navViewName).toBe('banana'); - expect($ionicViewService.isCurrentStateNavView).toHaveBeenCalledWith('banana'); + expect(tab.navViewName).toBe('banana'); + expect($ionicViewService.isCurrentStateNavView).toHaveBeenCalledWith('banana'); - $ionicViewService.isCurrentStateNavView.reset(); - isCurrent = true; - $rootScope.$broadcast('$stateChangeSuccess'); + $ionicViewService.isCurrentStateNavView.reset(); + isCurrent = true; + $rootScope.$broadcast('$stateChangeSuccess'); - expect($ionicViewService.isCurrentStateNavView).toHaveBeenCalledWith('banana'); - expect(tabsCtrl.select).toHaveBeenCalledWith(tab); - })); + expect($ionicViewService.isCurrentStateNavView).toHaveBeenCalledWith('banana'); + expect(tabsCtrl.select).toHaveBeenCalledWith(tab); + })); + }); it('should transclude on $tabSelected=true', function() { setup('', '
');