Last Updated: October 30, 2021
·
62.81K
· 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.

13 Responses
Add your response

Great article! Very useful :)

over 1 year ago ·

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

over 1 year ago ·

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

over 1 year ago ·

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 ·

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 ·

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 ·

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 ·

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

over 1 year ago ·

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 ·

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 ·

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 ·

@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 ·

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 ·