Reputation: 80505
This is the HTML (fragment):
<div class="header" ng-controller="Header" ng-hide="hideHeader"></div>
<div class="page" ng-view></div>
The .header
has the same controller always, while the .page
has different controllers based on the route.
The problem is that hideHeader
is set in the controller for the current URL.
What would be the best way to tell the Header
controller that the controller for the current route has changed the value of hideHeader
?
I don't think setting it on the $routeScope
is the right way. Also, most of the time, the header will be visible, there are very few pages that want to hide it.
Another idea is for that variable to be set in the config()
method:
$routeProvider
.when('/',
{
templateUrl:'views/hello.html',
controller:'Hello',
hideHeader:true
});
However, I am not sure that's a proper "AngularJS" way of doing that.
What's my best option?
Thank you.
Upvotes: 1
Views: 129
Reputation: 3538
You could listen for the $locationChangeStart
or $locationChangeSuccess
events in your header controller and then hide it based on the change in the url.
http://docs.angularjs.org/api/ng.$location
From the AngularJS API Docs
$locationChangeStart
Broadcasted before a URL will change. This change can be prevented by calling preventDefault method of the event. See ng.$rootScope.Scope#$on for more details about event object. Upon successful change $locationChangeSuccess is fired.
Type:
broadcast
Target:
root scope
Parameters
Param Type Details
angularEvent Object Synthetic event object.
newUrl: string New URL
oldUrl: (optional) string URL that was before it was changed.
EDIT
angular.module('myApp',[]).config(['$routeProvider',function($routeProvider){
// application routes here
}).run(['$rootScope','$location',function($rootScope,$location){
$rootScope.$on('$locationChangeStart',function(evt,newPath,oldPath){
switch(newPath){
case '/some/path':
case '/some/other/path':
case '/some/more/paths':
$rootScope.$broadcast('header.hide');
break;
default:
$rootScope.$broadcast('header.show');
break;
}
});
}])
.controller('HeaderCtrlr',['$scope',function($scope){
$scope.hideFlag = false;
$scope.$on('header.hide',function(){
$scope.hideFlag = true;
});
$scope.$on('header.show',function(){
$scope.hideFlag = false;
});
}]);
Upvotes: -1
Reputation: 24676
I'd lean towards a service since the Angular team states "having two controllers that want access to the same data is a classic sign that you want a service." (One of the places they mention this is in their Angular Best Practices discussion: http://www.youtube.com/watch?v=ZhfUv0spHCY). And they also discuss services being the right place for shared state (with thin controllers that are the "glue between views and services").
So, something either like this:
myApp.service('headerStatus', function () {
var hideHeader = true;
this.hideHeader = function() {
return hideHeader;
};
this.setHeader = function(visibility) {
hideHeader = visibility;
};
});
Then there's a bunch of ways to tie into it, but here's a simple one:
myApp.controller('Header', function ($scope,headerStatus) {
$scope.hideHeader = headerStatus.hideHeader();
});
And a fiddle of this: http://jsfiddle.net/Yxbsg/1/
Or potentially you could use a value:
myApp.value('headerStatus',true);
myApp.controller('Header', function ($scope,headerStatus) {
$scope.hideHeader = headerStatus;
});
Upvotes: 2