fix(ionView): observe for attr changes

This commit is contained in:
Adam Bradley
2014-11-13 14:20:11 -06:00
parent 18b6e23ba9
commit 9e5caf5983
2 changed files with 118 additions and 12 deletions

View File

@@ -12,6 +12,7 @@ function($scope, $element, $attrs, $compile, $ionicHistory, $ionicViewSwitcher)
var navViewCtrl;
var navBarDelegateHandle;
var hasViewHeaderBar;
var deregisters = [];
var deregIonNavBarInit = $scope.$on('ionNavBar.init', function(ev, delegateHandle){
// this view has its own ion-nav-bar, remember the navBarDelegateHandle for this view
@@ -38,13 +39,8 @@ function($scope, $element, $attrs, $compile, $ionicHistory, $ionicViewSwitcher)
// add listeners for when this view changes
$scope.$on('$ionicView.beforeEnter', self.beforeEnter);
$scope.$on('$ionicView.afterEnter', self.afterEnter);
// watch to see if the hideNavBar attribute changes
var hideNavAttr = isDefined($attrs.hideNavBar) ? $attrs.hideNavBar : 'false';
$scope.$watch(hideNavAttr, function(value) {
navViewCtrl.showBar(!value);
});
$scope.$on('$ionicView.afterEnter', afterEnter);
$scope.$on('$ionicView.beforeLeave', deregisterObservers);
};
self.beforeEnter = function(ev, transData) {
@@ -68,16 +64,55 @@ function($scope, $element, $attrs, $compile, $ionicHistory, $ionicViewSwitcher)
transition: transData.transition,
transitionId: transData.transitionId,
shouldAnimate: transData.shouldAnimate,
showBack: transData.showBack && !$attrs.hideBackButton,
showBack: transData.showBack && !attrTrue('hideBackButton'),
buttons: buttons,
navBarDelegate: navBarDelegateHandle || null,
showNavBar: !($attrs.hideNavBar === "true" || $attrs.hideNavBar === ""),
showNavBar: !attrTrue('hideNavBar'),
hasHeaderBar: !!hasViewHeaderBar
});
// make sure any existing observers are cleaned up
deregisterObservers();
}
};
function afterEnter() {
// only listen for title updates after it has entered
// but also deregister the observe before it leaves
var viewTitleAttr = isDefined($attrs.viewTitle) && 'viewTitle' || isDefined($attrs.title) && 'title';
if (viewTitleAttr) {
deregisters.push($attrs.$observe(viewTitleAttr, function(val) {
navViewCtrl.title(val);
$ionicHistory.currentTitle(val);
}));
}
if (isDefined($attrs.hideBackButton)) {
deregisters.push($attrs.$observe('hideBackButton', function() {
navViewCtrl.showBackButton(!attrTrue('hideBackButton'));
}));
}
if (isDefined($attrs.hideNavBar)) {
deregisters.push($attrs.$observe('hideNavBar', function() {
navViewCtrl.showBar(!attrTrue('hideNavBar'));
}));
}
$ionicViewSwitcher.setActiveView($element.parent());
}
function deregisterObservers() {
// remove all existing $attrs.$observe's
for (var x = 0; x < deregisters.length; x++) {
deregisters[x]();
}
deregisters = [];
}
function generateButton(html) {
if (html) {
// every time a view enters we need to recreate its view buttons if they exist
@@ -86,9 +121,9 @@ function($scope, $element, $attrs, $compile, $ionicHistory, $ionicViewSwitcher)
}
self.afterEnter = function(ev, transitionData) {
$ionicViewSwitcher.setActiveView($element.parent());
};
function attrTrue(key) {
return $attrs[key] == 'true' || $attrs[key] === '';
}
self.navElement = function(type, html) {

View File

@@ -11,7 +11,9 @@ describe('ionView directive', function() {
el = angular.element('<ion-view '+(attrs||'')+'>');
el.data('$ionNavViewController', {
beforeEnter: function(d) { beforeEnterData = d; },
title: jasmine.createSpy('title'),
showBar: jasmine.createSpy('showBar'),
showBackButton: jasmine.createSpy('showBackButton')
});
content && el.html(content);
@@ -116,4 +118,73 @@ describe('ionView directive', function() {
expect( beforeEnterData.hasHeaderBar ).toBe(true);
}));
it('should only observe title attr after afterEnter and before beforeLeave', inject(function($rootScope) {
var el = setup('view-title="{{ myTitle }}"', {myTitle: 'My Title'});
$rootScope.$broadcast('$ionicView.beforeEnter', {});
var spy = el.data('$ionNavViewController').title;
expect(spy).not.toHaveBeenCalled();
spy.reset();
$rootScope.$broadcast('$ionicView.afterEnter', {});
expect(spy).not.toHaveBeenCalled();
spy.reset();
el.scope().myTitle = 'My New Title';
$rootScope.$digest();
expect(spy).toHaveBeenCalledWith('My New Title');
spy.reset();
$rootScope.$broadcast('$ionicView.beforeLeave', {});
el.scope().myTitle = 'My Other New Title';
$rootScope.$digest();
expect(spy).not.toHaveBeenCalled();
spy.reset();
}));
it('should only observe hideNavBar attr after afterEnter and before beforeLeave', inject(function($rootScope) {
var el = setup('hide-nav-bar="{{ hide }}"', {hide: false});
$rootScope.$broadcast('$ionicView.beforeEnter', {});
var spy = el.data('$ionNavViewController').showBar;
expect(spy).not.toHaveBeenCalled();
spy.reset();
$rootScope.$broadcast('$ionicView.afterEnter', {});
expect(spy).not.toHaveBeenCalled();
spy.reset();
el.scope().hide = true;
$rootScope.$digest();
expect(spy).toHaveBeenCalledWith(false);
spy.reset();
$rootScope.$broadcast('$ionicView.beforeLeave', {});
el.scope().hide = false;
$rootScope.$digest();
expect(spy).not.toHaveBeenCalled();
spy.reset();
}));
it('should only observe hideBackButton attr after afterEnter and before beforeLeave', inject(function($rootScope) {
var el = setup('hide-back-button="{{ hide }}"', {hide: false});
$rootScope.$broadcast('$ionicView.beforeEnter', {});
var spy = el.data('$ionNavViewController').showBackButton;
expect(spy).not.toHaveBeenCalled();
spy.reset();
$rootScope.$broadcast('$ionicView.afterEnter', {});
expect(spy).not.toHaveBeenCalled();
spy.reset();
el.scope().hide = true;
$rootScope.$digest();
expect(spy).toHaveBeenCalledWith(false);
spy.reset();
$rootScope.$broadcast('$ionicView.beforeLeave', {});
el.scope().hide = false;
$rootScope.$digest();
expect(spy).not.toHaveBeenCalled();
spy.reset();
}));
});