I am using ng-view to include AngularJS partial views, and I want to update the page title and h1 header tags based on the included view. These are out of scope of the parti
You could define controller at the <html>
level.
<html ng-app="app" ng-controller="titleCtrl">
<head>
<title>{{ Page.title() }}</title>
...
You create service: Page
and modify from controllers.
myModule.factory('Page', function() {
var title = 'default';
return {
title: function() { return title; },
setTitle: function(newTitle) { title = newTitle }
};
});
Inject Page
and Call 'Page.setTitle()' from controllers.
Here is the concrete example: http://plnkr.co/edit/0e7T6l
Here's a different way to do title changes. Maybe not as scalable as a factory function (which could conceivably handle unlimited pages) but it was easier for me to understand:
In my index.html I started like this:
<!DOCTYPE html>
<html ng-app="app">
<head>
<title ng-bind-template="{{title}}">Generic Title That You'll Never See</title>
Then I made a partial called "nav.html":
<div ng-init="$root.title = 'Welcome'">
<ul class="unstyled">
<li><a href="#/login" ng-click="$root.title = 'Login'">Login</a></li>
<li><a href="#/home" ng-click="$root.title = 'Home'">Home</a></li>
<li><a href="#/admin" ng-click="$root.title = 'Admin'">Admin</a></li>
<li><a href="#/critters" ng-click="$root.title = 'Crispy'">Critters</a></li>
</ul>
</div>
Then I went back to "index.html" and added the nav.html using ng-include and the ng-view for my partials:
<body class="ng-cloak" ng-controller="MainCtrl">
<div ng-include="'partials/nav.html'"></div>
<div>
<div ng-view></div>
</div>
Notice that ng-cloak? It doesn't have anything to do with this answer but it hides the page until it's done loading, a nice touch :) Learn how here: Angularjs - ng-cloak/ng-show elements blink
Here's the basic module. I put it in a file called "app.js":
(function () {
'use strict';
var app = angular.module("app", ["ngResource"]);
app.config(function ($routeProvider) {
// configure routes
$routeProvider.when("/", {
templateUrl: "partials/home.html",
controller:"MainCtrl"
})
.when("/home", {
templateUrl: "partials/home.html",
controller:"MainCtrl"
})
.when("/login", {
templateUrl:"partials/login.html",
controller:"LoginCtrl"
})
.when("/admin", {
templateUrl:"partials/admin.html",
controller:"AdminCtrl"
})
.when("/critters", {
templateUrl:"partials/critters.html",
controller:"CritterCtrl"
})
.when("/critters/:id", {
templateUrl:"partials/critter-detail.html",
controller:"CritterDetailCtrl"
})
.otherwise({redirectTo:"/home"});
});
}());
If you look toward the end of the module, you'll see that I have a critter-detail page based on :id. It's a partial that is used from the Crispy Critters page. [Corny, I know - maybe it's a site that celebrates all kinds of chicken nuggets ;) Anyway, you could update the title when a user clicks on any link, so in my main Crispy Critters page that leads to the critter-detail page, that's where the $root.title update would go, just like you saw in the nav.html above:
<a href="#/critters/1" ng-click="$root.title = 'Critter 1'">Critter 1</a>
<a href="#/critters/2" ng-click="$root.title = 'Critter 2'">Critter 2</a>
<a href="#/critters/3" ng-click="$root.title = 'Critter 3'">Critter 3</a>
Sorry so windy but I prefer a post that gives enough detail to get it up and running. Note that the example page in the AngularJS docs is out of date and shows a 0.9 version of ng-bind-template. You can see that it's not that much different.
Afterthought: you know this but it's here for anyone else; at the bottom of the index.html, one must include the app.js with the module:
<!-- APP -->
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>
jkoreska's solution is perfect if you know the titles before hand, but you may need to set the title based on data you get from a resource etc.
My solution requires a single service. Since the rootScope is the base of all DOM elements, we don't need to put a controller on the html element like someone mentioned
app.service('Page', function($rootScope){
return {
setTitle: function(title){
$rootScope.title = title;
}
}
});
doctype html
html(ng-app='app')
head
title(ng-bind='title')
// ...
app.controller('SomeController', function(Page){
Page.setTitle("Some Title");
});
While others may have better methods, I was able to use $rootScope in my controllers, as each of my views/templates has a distinct controller. You will need to inject the $rootScope in each controller. While this may not be ideal, it is functioning for me, so I thought I should pass it along. If you inspect the page, it adds the ng-binding to the title tag.
Example Controller:
myapp.controller('loginPage', ['$scope', '$rootScope', function ($scope, $rootScope) {
// Dynamic Page Title and Description
$rootScope.pageTitle = 'Login to Vote';
$rootScope.pageDescription = 'This page requires you to login';
}]);
Example Index.html header:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta name="description" content="{{pageDescription}}">
<meta name="author" content="">
<link rel="shortcut icon" href="../../assets/ico/favicon.ico">
<base href="/">
<title>{{pageTitle}}</title>
You can also set the pageTitle and pageDescription to dynamic values, such as returning data from a REST call:
$scope.article = restCallSingleArticle.get({ articleID: $routeParams.articleID }, function() {
// Dynamic Page Title and Description
$rootScope.pageTitle = $scope.article.articletitle;
$rootScope.pageDescription = $scope.article.articledescription;
});
Again, others may have better ideas on how to approach this, but since I am using a pre-rendering, my needs are being met.