How to change page title in Angular using $routeProvider
Asked Answered
L

3

13

I found several similar questions, however none of the answers helped. They all seem to involve some type of $location dependencies that I'm unable to get injected right.

My code below:

(function() {

    // App dependencies
    var app = angular.module('portalExchange',
                        ['ngRoute',
                         'app-products',
                         'app-manage',
                         'app-profile']);

    // [ Main Controller ] : PortalController
    app.controller('PortalController', function($scope) {
        if ($('.top_link_dashboard').hasClass('unactive_top')) {
            $('.top_link_dashboard').removeClass('unactive_top');
            $('.top_link_dashboard').addClass('active_top');
        }
    });

    // Controller for Dashboard
    app.controller('DashboardController', function() {
    });

    // Controller for Developers
    app.controller('DevelopersController', function($scope) {
        // Page.setTitle('Developers');
    });

    // Controller for Quote
    app.controller('QuoteController', function($scope) {
        // Page.setTitle('Begin Quote');
    });

    // Directive for Header
    app.directive('appHeader', function () {
        // Type of Directive, E for element, A for Attribute
        // url of a template
        return {
            restrict: 'E',
            templateUrl: 'templates/modules/globals/app-header.html'
        };
    });

    // Directive for Footer
    app.directive('appFooter', function () {
        return {
            restrict: 'E',
            templateUrl: 'templates/modules/globals/app-footer.html',
            controller: function(){
                this.date = Date.now();
            },
            controllerAs:'footer'
        };
    });

    // configure our routes
    app.config(function($routeProvider) {
        $routeProvider

        // route for the dashboard page
        .when('/', {
            templateUrl : 'templates/sections/app-dashboard.html',
            controller  : 'DashboardController'
        })

        // route for the dashboard page
        .when('/dashboard', {
            title : 'My Dashboard',
            templateUrl : 'templates/sections/app-dashboard.html',
            controller  : 'DashboardController'
        })

        // route : Developers Page
        .when('/developers', {
            title : 'For Developers',
            templateUrl : 'templates/sections/app-developers.html',
            controller  : 'DevelopersController'
        })

        // route : Begin Quote
        .when('/quote', {
            title : 'Begin Quote',
            templateUrl : 'templates/sections/app-quote.html',
            controller  : 'QuoteController'
        });
    });

    app.run(['$rootScope', '$route', function($rootScope) {
        $rootScope.$on('$routeChangeSuccess', function(newVal, oldVal) {
            if (oldVal !== newVal) {
                document.title = $route.current.title;
            }
        });
    }]);

})();

The RUN function

app.run(['$rootScope', '$route', function($rootScope) {
    $rootScope.$on('$routeChangeSuccess', function(newVal, oldVal) {
        if (oldVal !== newVal) {
            document.title = $route.current.title;
        }
    });
}]);

HTML

<!DOCTYPE html>
<html lang="en" ng-app="portalExchange" ng-controller="PortalController as portal">
<head>
    <meta charset="utf-8">
    <title ng-bind="title">myApp</title>
</head>
Lenssen answered 10/10, 2014 at 21:5 Comment(3)
What is the error you get in the console?Alvinia
Why not just call a document.title = $scope.myTitle line every time the location changes?Manizales
@Mike Exactly, no need of one more watcher binding.Emetic
E
48

The way I do it is quite simple. In route configuration you define title:

.when('/dashboard', {
    title : 'My Dashboard',
    templateUrl : 'templates/sections/app-dashboard.html',
    controller  : 'DashboardController'
})

then you listen $routeChangeSuccess event and just set document.title. In application run block (the best place for this):

app.run(['$rootScope', '$route', function($rootScope, $route) {
    $rootScope.$on('$routeChangeSuccess', function() {
        document.title = $route.current.title;
    });
}]);

The benefit of this approach is that it allows you to avoid one more binding ng-bind="title", which is good.

Emetic answered 10/10, 2014 at 21:10 Comment(6)
sorry, still having trouble with this :( $root is undefined, I'm not sure I'm injecting it in correctly... multiple errors. I am uploading my latest code and will post a link soonLenssen
Sorry, of course you also need to inject $route service. Take a look at updated answer.Emetic
You need to inject $rootScope and $route services into run function, like in my example in the answer.Emetic
@Emetic The signature of $routeChangeSuccess is (event, currentRoute, previousRoute) so isn't your check (oldValue !== newVal) redundant, or am I missing something? Maybe collect all three params in your function closure and then check (currentRoute !== previousRoute) but even that seems a little redundant since we are in routeChangeSuccess anyway.Mistreat
but, +1 for a succinct solution!Mistreat
@Mistreat Good catch, indeed (oldValue !== newVal) is redundant as it's never false.Emetic
I
4

This is another way

app.run(['$rootScope', function($rootScope) {
    $rootScope.$on('$routeChangeSuccess', function(_, current) {
        document.title = current.$$route.title;
    });
}]);

Because sometimes $route injection causes problem (for example, in running unit tests).

Indaba answered 17/9, 2015 at 1:37 Comment(0)
C
2

This is a little of topic, but I was trying to manage the page title in an angular application that uses ui-router and I ran into a couple of issues. First, of course, I had to change route and $routeChangeSuccess to $state and $stateChangeSuccess and second, I had an issue with the page title getting updated before the browser could add the previous page title to the history, so I had to add a timeout to the event handler resulting the following code:

angular.module('myApp').run(appRunFunction);

appRunFunction.$inject = ['$rootScope', '$state', '$timeout'];

function appRunFunction($rootScope, $state, $timeout) {
    $rootScope.$on('$stateChangeSuccess', function() {
        $timeout(function() { document.title = $state.current.title; }, 100);
    });
}
Confessional answered 19/8, 2015 at 19:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.