diff --git a/js/angular/controller/navViewController.js b/js/angular/controller/navViewController.js
index bb7af55ab5..9a8ce5704f 100644
--- a/js/angular/controller/navViewController.js
+++ b/js/angular/controller/navViewController.js
@@ -12,6 +12,7 @@ IonicModule
function($scope, $element, $attrs, $compile, $controller, $ionicNavBarDelegate, $ionicNavViewDelegate, $ionicHistory, $ionicViewSwitcher) {
var DATA_ELE_IDENTIFIER = '$eleId';
+ var DATA_DESTROY_ELE = '$destroyEle';
var VIEW_STATUS_ACTIVE = 'active';
var VIEW_STATUS_CACHED = 'cached';
var HISTORY_AFTER_ROOT = 'after-root';
@@ -41,6 +42,8 @@ function($scope, $element, $attrs, $compile, $controller, $ionicNavBarDelegate,
var deregisterInstance = $ionicNavViewDelegate._registerInstance(self, $attrs.delegateHandle);
$scope.$on('$destroy', deregisterInstance);
+ $scope.$on('$ionicHistory.deselect', self.cacheCleanup);
+
return viewData;
};
@@ -159,6 +162,16 @@ function($scope, $element, $attrs, $compile, $controller, $ionicNavBarDelegate,
};
+ self.cacheCleanup = function() {
+ var viewElements = $element.children();
+ for (var x = 0, l = viewElements.length; x < l; x++) {
+ if (viewElements.eq(x).data(DATA_DESTROY_ELE)) {
+ $ionicViewSwitcher.destroyViewEle(viewElements.eq(x));
+ }
+ }
+ };
+
+
self.clearCache = function() {
var viewElements = $element.children();
var viewElement, viewScope;
diff --git a/js/angular/controller/tabsController.js b/js/angular/controller/tabsController.js
index f6d0a4a275..f98c0af98b 100644
--- a/js/angular/controller/tabsController.js
+++ b/js/angular/controller/tabsController.js
@@ -45,6 +45,7 @@ function($scope, $ionicHistory, $element) {
_selectedTab = null;
tab.$tabSelected = false;
(tab.onDeselect || angular.noop)();
+ tab.$broadcast && tab.$broadcast('$ionicHistory.deselect');
}
};
diff --git a/test/unit/angular/directive/navView.unit.js b/test/unit/angular/directive/navView.unit.js
index 27945e2e48..721baf1887 100644
--- a/test/unit/angular/directive/navView.unit.js
+++ b/test/unit/angular/directive/navView.unit.js
@@ -102,8 +102,49 @@ describe('Ionic nav-view', function() {
ionViewCacheFalsePropertyState = {
template: 'ionViewCacheFalsePropertyState',
cache: false
- };
-
+ },
+ tabAbstractState = {
+ abstract: true,
+ views: {
+ 'root': {
+ template: '' +
+ '' +
+ '' +
+ '' +
+ 'Inline Tab
' +
+ ''
+ }
+ }
+ },
+ tab1page1State = {
+ views: {
+ 'tab1': {
+ template: 'tab1page1'
+ }
+ }
+ },
+ tab2page1State = {
+ views: {
+ 'tab2': {
+ template: 'tab2page1'
+ }
+ }
+ },
+ tab3page1State = {
+ views: {
+ 'tab3': {
+ template: 'tab3page1'
+ }
+ }
+ },
+ tab3page2NoCacheState = {
+ cache: false,
+ views: {
+ 'tab3': {
+ template: 'tab3page2NoCache'
+ }
+ }
+ }
beforeEach(module(function ($stateProvider) {
$stateProvider
.state('a', aState)
@@ -128,7 +169,12 @@ describe('Ionic nav-view', function() {
.state('ionView1', ionView1State)
.state('ionView2', ionView2State)
.state('ionViewCacheFalseAttr', ionViewCacheFalseAttrState)
- .state('ionViewCacheFalseProperty', ionViewCacheFalsePropertyState);
+ .state('ionViewCacheFalseProperty', ionViewCacheFalsePropertyState)
+ .state('tabAbstract', tabAbstractState)
+ .state('tabAbstract.tab1page1', tab1page1State)
+ .state('tabAbstract.tab2page1', tab2page1State)
+ .state('tabAbstract.tab3page1', tab3page1State)
+ .state('tabAbstract.tab3page2', tab3page2NoCacheState);
}));
beforeEach(inject(function(_$compile_, $ionicConfig, $rootScope) {
@@ -901,6 +947,70 @@ describe('Ionic nav-view', function() {
expect(divs.eq(0).text()).toBe('page2');
}));
+ it('should create and cache tabs', inject(function ($state, $q, $timeout, $compile, $ionicConfig) {
+ elem.append($compile('')(scope));
+
+ $state.go(tab1page1State);
+ $q.flush();
+ $timeout.flush();
+
+ var tab1Ele = elem[0].querySelector('ion-nav-view[name="tab1"]');
+ expect(tab1Ele.getAttribute('nav-view')).toBe('active');
+
+ $state.go(tab2page1State);
+ $q.flush();
+ $timeout.flush();
+
+ var tab2Ele = elem[0].querySelector('ion-nav-view[name="tab2"]');
+ expect(tab1Ele.getAttribute('nav-view')).toBe('cached');
+ expect(tab2Ele.getAttribute('nav-view')).toBe('active');
+
+ $state.go(tab3page1State);
+ $q.flush();
+ $timeout.flush();
+
+ var tab3Ele = elem[0].querySelector('ion-nav-view[name="tab3"]');
+ expect(tab1Ele.getAttribute('nav-view')).toBe('cached');
+ expect(tab2Ele.getAttribute('nav-view')).toBe('cached');
+ expect(tab3Ele.getAttribute('nav-view')).toBe('active');
+
+ $state.go(tab1page1State);
+ $q.flush();
+ $timeout.flush();
+
+ expect(tab1Ele.getAttribute('nav-view')).toBe('active');
+ expect(tab2Ele.getAttribute('nav-view')).toBe('cached');
+ expect(tab3Ele.getAttribute('nav-view')).toBe('cached');
+ }));
+
+ it('should not cache a tab with cache false state property', inject(function ($state, $q, $timeout, $compile, $ionicConfig) {
+ elem.append($compile('')(scope));
+
+ $state.go(tab3page2NoCacheState);
+ $q.flush();
+ $timeout.flush();
+ $timeout.flush();
+
+ var tab3NoCacheEle = elem[0].querySelector('ion-nav-view[name="tab3"]');
+ expect(tab3NoCacheEle.getAttribute('nav-view')).toBe('active');
+
+ var tab3InnerEle = tab3NoCacheEle.querySelector('[nav-view="active"]');
+ expect(tab3InnerEle.innerText).toEqual('tab3page2NoCache');
+
+ $state.go(tab1page1State);
+ $q.flush();
+ $timeout.flush();
+ $timeout.flush();
+
+ var tab1Ele = elem[0].querySelector('ion-nav-view[name="tab1"]');
+ expect(tab3NoCacheEle.getAttribute('nav-view')).toBe('cached');
+ expect(tab1Ele.getAttribute('nav-view')).toBe('active');
+ expect(tab1Ele.innerText).toEqual('tab1page1');
+
+ tab3InnerEle = tab3NoCacheEle.querySelector('[nav-view="active"]');
+ expect(tab3InnerEle).toBe(null);
+ }));
+
});
angular.module('ngMock').config(function ($provide) {