Question
I am migrating my AngularJS based app to use ui-router instead of the built in routing. I have it configured as shown below
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl : 'views/home.html',
data : { pageTitle: 'Home' }
})
.state('about', {
url: '/about',
templateUrl : 'views/about.html',
data : { pageTitle: 'About' }
})
});
How can I use the pageTitle variable to dynamically set the title of the page? Using the built in routing, I could do
$rootScope.$on("$routeChangeSuccess", function(currentRoute, previousRoute){
$rootScope.pageTitle = $route.current.data.pageTitle;
});
and then bind the variable in HTML as shown below
<title ng-bind="$root.pageTitle"></title>
Is there a similar event that I can hook into using ui-router? I noticed that there are 'onEnter' and 'onExit' functions but they seem to be tied to each state and will require me to repeat code to set the $rootScope variable for each state.
Answer
Use $stateChangeSuccess
.
You can put it in a directive:
app.directive('updateTitle', ['$rootScope', '$timeout',
function($rootScope, $timeout) {
return {
link: function(scope, element) {
var listener = function(event, toState) {
var title = 'Default Title';
if (toState.data && toState.data.pageTitle) title = toState.data.pageTitle;
$timeout(function() {
element.text(title);
}, 0, false);
};
$rootScope.$on('$stateChangeSuccess', listener);
}
};
}
]);
And:
<title update-title></title>
Demo: http://run.plnkr.co/8tqvzlCw62Tl7t4j/#/home
Code: http://plnkr.co/edit/XO6RyBPURQFPodoFdYgX?p=preview
Even with $stateChangeSuccess
the $timeout
has been needed for the history
to be correct, at least when I've tested myself.
Edit: Nov 24, 2014 - Declarative approach:
app.directive('title', ['$rootScope', '$timeout',
function($rootScope, $timeout) {
return {
link: function() {
var listener = function(event, toState) {
$timeout(function() {
$rootScope.title = (toState.data && toState.data.pageTitle)
? toState.data.pageTitle
: 'Default title';
});
};
$rootScope.$on('$stateChangeSuccess', listener);
}
};
}
]);
And:
<title>{{title}}</title>