How to dynamically update title tag?

14,885 views
Skip to first unread message

Dan

unread,
Jun 12, 2011, 7:24:16 PM6/12/11
to angular
I was wondering the best practice for updating the title tag using
angular. I know I could do this with jQuery but was feeling like I
should use angular. I did try using angular.element but I not sure I
know how to use it properly.

<title>Some starting title</title>

In most of my partial pages there will be an <h2>my page title</h2>
that I would like to use to replace the static title. It seems like I
would need to work with the root scope.

I tried figuring out how the angular docs does this, but am too much
of a nooby to ferret out the code that actually does this. From what
I've seen so far I need

1. a controller attached to <html>

2. <title ng:bind-template="mycompany.com: {{partialTitle}}">some
placeholder text</title>

3. <h2 ng:bind="partialTitle">My title from my partial page</h2>

4. some event after partial page loads

If anyone has a complete example, much appreciated.

TIA

Dan

Mårten Dolk

unread,
Jun 13, 2011, 5:00:05 AM6/13/11
to ang...@googlegroups.com
Interesting problem!

Should probably add something like this to the app I'm working on...

This is a somewhat hackish way to do it:

function MyCtrl($window) {
$window.document.title = 'Hello Title';
}
MyCtrl.$inject = ['$window'];


I think the magic at docs.angularjs.org is watching $location.hashPath
and then look up the page title in a data structure. For this approach
to work I guess you would need access to all the page titles in the
root-scope.

From http://docs.angularjs.org/docs-combined.js:

this.$watch('$location.hashPath', function(hashPath) {
if (hashPath.match(/^!/)) {
var parts = hashPath.substring(1).split('/');
self.sectionId = parts[1];
self.partialId = parts[2] || 'index';
self.pages = angular.Array.filter(NG_PAGES, {section:self.sectionId});
self.partialTitle = (angular.Array.filter(self.pages,
function(doc){return doc.id == self.partialId;})[0]||{}).name ||
'Error: Page Not Found!';
}
});

Another approach may be to add a $route.onChange(fn) and update the title there?

I would love to hear the angular devs take on this!

Cheers!
/Mårten


2011/6/13 Dan <hae...@gmail.com>:

> --
> You received this message because you are subscribed to the Google Groups "angular" group.
> To post to this group, send email to ang...@googlegroups.com.
> To unsubscribe from this group, send email to angular+u...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/angular?hl=en.
>
>

Witold Szczerba

unread,
Jun 13, 2011, 5:43:10 AM6/13/11
to ang...@googlegroups.com
You can always create a service for that:

something like this (writing directly in e-mail, so please verify)

angular.service('pageTitleSetter', function($window) {
return function(documentTitle) {
$window.document.title = documentTitle;
};
}, {$inject:'$window'});

And now, in any controller you can use it:

function MyCtrl(pageTitleSetter) {
pageTitleSetter('my page title');
}
MyCtrl.$inject = ['pageTitleSetter'];

Now your controller does require a 'kitchen sink' to setup a title, it
is readable and there is no need to make volatile assumptions when
writing tests.
What do you think?

Regards,
Witold Szczerba

Adam Pohorecki

unread,
Jun 13, 2011, 5:59:56 AM6/13/11
to ang...@googlegroups.com
I'm using something very similar in my application (the service can
also be used to get the title). Initially we used to set the page
title in controllers but now we use a widget for that instead.

Vojta Jina

unread,
Jun 13, 2011, 8:58:48 AM6/13/11
to ang...@googlegroups.com
I would use angular's two way data-binding. That's exactly what we do in docs...

// bind title to variable in root scope
<title ng:bind-template="Prefix: {{pageTitle}}"></title>

If you need to change to value from loaded partial, you can get the value for example from <h2> and then set to pageTitle variable, or the partial could include code to set the variable...
See this simple example: https://gist.github.com/1022724

V.

Misko Hevery

unread,
Jun 14, 2011, 11:40:56 AM6/14/11
to ang...@googlegroups.com
<title>{{greeting}}</title> also works, but not in ie, go figure. :-) so
<title ng:bind-template="Prefix: {{pageTitle}}"></title> is better


<html xmlns:ng="http://angularjs.org/" ng:controller="MyApp"> 
 <script src="http://code.angularjs.org/angular-0.9.16.min.js" ng:autobind></script>
 <script>
   function MyApp(){
     this.greeting = 'Hello World!'
   }
 </script>
 <title ng:bind-template="angular: {{greeting}}"></title>
 <body> 
  <p>{{greeting}}</p>
 </body>
</html>


-- Misko

--
You received this message because you are subscribed to the Google Groups "angular" group.
To view this discussion on the web visit https://groups.google.com/d/msg/angular/-/5mwaEwAm-QUJ.

Haralan Dobrev

unread,
Sep 20, 2012, 3:28:45 PM9/20/12
to ang...@googlegroups.com
I would prefer setting the title from a custom HTTP header for AJAX requests.

When you receive a request from the server (maybe on $viewContentLoaded event?) you would check the HTTP headers for e.g. X-Ajax-Title.

Thus you would not require looking for h1, h2 tags etc.

This could be managed by a separate service as well.

The problem with that approach is you would not be able to set the title of a page when it is not related to any HTTP request.


From REST API perspective the custom header allows you to specify a name of a data response without changing the data.

alm...@gmail.com

unread,
Sep 29, 2012, 12:29:19 AM9/29/12
to ang...@googlegroups.com
I wasn't able to get this to work, I did update the code to use ng-bind but still noting maybe I'm missing something? 

 

On Monday, June 13, 2011 3:58:48 PM UTC+3, Vojta Jína wrote:

Ben Nadel

unread,
Sep 30, 2012, 10:09:42 AM9/30/12
to ang...@googlegroups.com
I've been recently doing this with a "setter" method stored in a $scope at the top of the prototype chain:

http://www.bennadel.com/blog/2424-Setting-Prototype-Properties-Using-Inherited-Scope-Methods-In-AngularJS.htm

I've been pretty pleased with this approach, so far. Granted, I'm working on my *first* AngularJS app, so I'm still figuring it all out.

This approach also allows for some interesting decoration opportunities:

http://www.bennadel.com/blog/2425-Decorating-Scope-Methods-In-The-AngularJS-Prototype-Chain.htm

Cheers,
Ben Nadel

Gopal Patel

unread,
Sep 30, 2012, 11:13:05 AM9/30/12
to ang...@googlegroups.com
Wow didn't knew that I was using event to set title but this is much better
--
You received this message because you are subscribed to the Google Groups "AngularJS" group.

To post to this group, send email to ang...@googlegroups.com.
To unsubscribe from this group, send email to angular+u...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular?hl=en.
 
 

Almog

unread,
Oct 2, 2012, 11:26:31 AM10/2/12
to ang...@googlegroups.com
Thanks this is great

bourget....@gmail.com

unread,
Jan 8, 2013, 1:50:41 PM1/8/13
to ang...@googlegroups.com

What I did:

in my .config() call, injecting $routeProvider:

.when('/', {templateUrl: "/path/to/home.html",
            controller: 'HomeCtrl',
            title: 'Home'})

in my .run() call:

    $rootScope.page_title = 'Admin';
    $rootScope.$on('$routeChangeSuccess', function() {
      $rootScope.page_title = $route.current.$route.title;
    });

in my .html file:

        <title ng-bind="$root.page_title + ' - Suffix'">Admin - Suffix</title>

That way, I keep my routes and titles cleanly at one place.

Alexandre Bourget
Tenscores.com

Nicolas Duvieusart Déry

unread,
Mar 9, 2013, 4:38:13 PM3/9/13
to ang...@googlegroups.com, bourget....@gmail.com
I am using this method to alter the page title and would like to include variables in my page title. I have tried doing like so

.when('/work/:projectID', {
  title: '{{projectID}},
  templateUrl: 'views/project-detail.html',
  controller: 'ProjectDetailCtrl'
})

but it simply shows "{{projectID}}" in the title, not replacing it. Is this possible?

Peter Bacon Darwin

unread,
Mar 10, 2013, 4:41:51 PM3/10/13
to ang...@googlegroups.com
Check where you are placing you ng-app directive - is it outside the head tag? i.e. on html?


--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.

To post to this group, send email to ang...@googlegroups.com.

Nicolas Duvieusart Déry

unread,
Mar 10, 2013, 4:46:08 PM3/10/13
to ang...@googlegroups.com
I placed the ng-app directive on the html attribute. But head is within html so it should be OK no?

<html ng-app="app">
  <head>
    <title ng-bind="…">…</tile>
  </head>
...


Nicolas


--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/xG-zIC-xBXE/unsubscribe?hl=en-US.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.

Peter Bacon Darwin

unread,
Mar 10, 2013, 6:02:20 PM3/10/13
to ang...@googlegroups.com
:-)
Should have actually read your code!
Ditch the "title" property from your route and then you should be doing something like this in your ProjectDetailCtrl:

function($scope,$routeParams) {
  $scope.$root.page_title = $routeParams.projectID;
}

Nicolas Duvieusart Déry

unread,
Mar 10, 2013, 6:10:50 PM3/10/13
to ang...@googlegroups.com
Is there a way to keep the title in the route[ing] part of the code, so all my titles are set form one place. I imagine I could use some regex to manually grab that part of the URL, or something with $location, and insert it like so, without having to pass a variable. But this feel redundant as Angular is already matching it with the route.


Nicolas

Nicolas Duvieusart Déry

unread,
Mar 10, 2013, 9:35:07 PM3/10/13
to ang...@googlegroups.com
Nevermind, you can keep the "title" attribute in the .when() for all pages and just overwrite it in specific controller, which will work. Thanks a lot!


Nicolas




Nicolas


To unsubscribe from this group and stop receiving emails from it, send an email to angular+unsubscribe@googlegroups.com.

To post to this group, send email to ang...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/xG-zIC-xBXE/unsubscribe?hl=en-US.
To unsubscribe from this group and all its topics, send an email to angular+unsubscribe@googlegroups.com.

To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+unsubscribe@googlegroups.com.

To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/xG-zIC-xBXE/unsubscribe?hl=en-US.
To unsubscribe from this group and all its topics, send an email to angular+unsubscribe@googlegroups.com.
Message has been deleted

Anthony Perot

unread,
Nov 16, 2013, 3:41:53 PM11/16/13
to ang...@googlegroups.com
I did it this way:

<title ng-controller="titleController">MySite - {{  pageTitle }}</title>

 .config(['$routeProvider',
        function($routeProvider) {
            $routeProvider
                .when('/home', {
                    templateUrl: 'templates/home.html',
                    controller: 'homeController',
                    pageTitle: 'HomePage',
                    navbarElement: '#navbar_homepage'
                })
                .when('/test', {
                    templateUrl: 'templates/test.html',
                    controller: 'testController',
                    pageTitle: 'Test',
                    navbarElement: '#navbar_test'
                })
                .otherwise({
                    redirectTo: '/home'
                });
        }]);

angular.module('mysite.controllers')
    .controller('titleController', function($scope, $route, $log){
        $scope.$on('$routeChangeSuccess', function(){
            $scope.pageTitle = $route.current.pageTitle;
        });
    })
Reply all
Reply to author
Forward
0 new messages