vcfo4q
Last Updated: February 25, 2016
·
49.52K
· igama
159f249362b6765a910afaf30573cf24

AngularJS : Change title based on Route

AngularJS is used to build single page WebApps. Considering it's nature, you will only have 1 Title for your page, so even if you go to '/product' or '/about', you would see the same Title on the Browser. Not really user friendly...

Where is one possible solution around this problem.

On your HTML, change the title tag to include a ng-bind:

<title ng-bind="'MyApp - ' + $root.title">MyApp - Welcome</title>

On your app.js:

$routeProvider
      .when('/product', {templateUrl: '/partials/product.html',  controller: 'ProductCtrl', title: 'Discover our Product'})
      .when('/about', {templateUrl: '/partials/about.html', controller: 'AboutCtrl', title: 'About US'});

on your run(), add a $rootScope.$on:

$rootScope.$on("$routeChangeSuccess", function(currentRoute, previousRoute){
    //Change page title, based on Route information
    $rootScope.title = $route.current.title;
  });

Note: The reason I'm using ng-bind instead of the angular template bind '{{ expression }}' is expressed on the documentation :

It is preferrable to use ngBind instead of {{ expression }} when a template is momentarily displayed by the browser in its raw state before Angular compiles it.

Say Thanks
Respond

14 Responses
Add your response

7791

Great article! Very useful :)

over 1 year ago ·
7793

Yes, Great Article! I have been looking for a nice way to do this. Thanks!

over 1 year ago ·
7794
Bb92524137114d812aa1cbbe70d35365

There is also ng-bind-template that will let you do the binding more cleanly.

over 1 year ago ·
7806
B9512394f68a44e6162b3984e08d22df

Nice trick!

Minor enhancement:

$rootScope.$on("$routeChangeSuccess", function(event, currentRoute, previousRoute) {
    $rootScope.title = currentRoute.title;
});

This way you do not have to inject $route in run().
Note that the $routeChangeSuccess event takes 3 parameters.

over 1 year ago ·
7878
Screen shot 2011 09 12 at 8.50.54 am  blue

If you need even more control over title, checkout titleService in ng-boilerplate project. Also tests are there.

ng-boilerplate/src/common/titleService

I like this idea more, because you can change title from Controller, so it can be some more dynamic value like unseen messages, or chat oposite name. Route name simply isn't enough sometimes.

over 1 year ago ·
8589
1505228 10153667646265066 1410509922 n

Thank you for this tip. I just don't know why there isn't any documentation about the $root used in the view. It just seems to not even exists on Angularjs.org

over 1 year ago ·
10221
Dan hunsaker   2015 05 02

Every variable you reference from a binding (be it ng-bind or {{}}) is treated as a scope property. That means {{window.location.href()}} won't work unless you also do $scope.window = $window (and inject $window, of course). It also means that the $root in this view is actually referring to $scope.$root. This is a property of the $rootScope that refers to $rootScope itself, and since every non-isolate scope inherits from its parents, $scope.$root - or $root in a binding - gets you $rootScope.

You're right, though. This should be documented. The Angular docs are notoriously incomplete.

over 1 year ago ·
12791
Ccbce1a24434b17ad84d5865593716ee

You don't have any dates anywhere on this page, not even in comments! So I'm not sure how long ago this was written. But if you're using UI-Router, it's pretty easy. Here's a sample indx.html that shows it in action. https://github.com/angular-ui/ui-router/blob/master/sample/index.html

Note the

<title ng-bind="$state.current.name">My App name - this text will be replaced</title>
over 1 year ago ·
12798
159f249362b6765a910afaf30573cf24

@tylercollier it was already written some months ago. Thanks for the tip on ui-router ;)

over 1 year ago ·
13812
6bb8d259b6b46a59ec66aadbd2b13015

This is good! Many other solutions that I saw involved changing the title manually in controllers, which is acceptable if you have 3 or 5 controllers, not up to 20 or more... Making the title an attribute of the route was certainly the most elegant way to go. I'm just concerned about having to bind the title attribute manually to the $rootScope on $routeChangeSuccess. I'll try to find a yet cleaner way and post here :) Um abra├žo!

over 1 year ago ·
15531

Hey guys, is there any way we can have configurable page titles? I have created a service with a getter/setter method, and I call it on $stateChangeSuccess, to set the page title in the $scope, where I can pull it from later on on the view. Is this the right way to do it?

over 1 year ago ·
15762
84b58de6e2ec6380bbcc813201c403a0

This looks really great. Do you know if there is any way to make the title, dynamic. Set it to values from the routeParam perhaps?

over 1 year ago ·
16331
Cd2f0ae4617476af515cb312f4143b86

@divya-sambasivan:

You can use $interpolate[1] like so:

$rootScope.$on("$routeChangeSuccess", function(currentRoute, previousRoute){
    //Change page title, based on Route information
    var titleExp = $interpolate($route.current.title);
    $rootScope.title = titleExp($route.current.params);
});

[1] https://docs.angularjs.org/api/ng/service/$interpolate

over 1 year ago ·
21777
None

Thanks you very much for the idea @ibrahima !

With ui-router you can set the window title like this (kinda hacky!):

$rootScope.$on('$stateChangeSuccess', function() {
    var titleExp = $interpolate($state.current.data.pageTitle);
    $document[0].title = titleExp($state.$current.locals.resolve.$$values);
});

And:

...
data: {
    pageTitle: "{{resolvedItem.name}} - My Apps"
}
...
over 1 year ago ·