vcfo4q
Last Updated: September 22, 2018
·
53.17K
· igama

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.

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

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

over 1 year ago ·
7806

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

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

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

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

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

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

over 1 year ago ·
13812

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

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

@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

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 ·