使用UI-Router设置页面标题

我正在迁移我的基于AngularJS的应用程序使用ui路由器,而不是内置路由。 我已经configuration如下所示

.config(function($stateProvider, $urlRouterProvider) { $urlRouterProvider.otherwise('/home'); $stateProvider .state('home', { url: '/home', templateUrl : 'views/home.html', data : { pageTitle: 'Home' } }) .state('about', { url: '/about', templateUrl : 'views/about.html', data : { pageTitle: 'About' } }) }); 

我如何使用pageTitlevariables来dynamic设置页面的标题? 使用内置路由,我可以做到

 $rootScope.$on("$routeChangeSuccess", function(currentRoute, previousRoute){ $rootScope.pageTitle = $route.current.data.pageTitle; }); 

然后在HTML中绑定variables,如下所示

 <title ng-bind="$root.pageTitle"></title> 

有没有类似的事件,我可以使用ui路由器挂钩? 我注意到有'onEnter'和'onExit'函数,但它们似乎与每个状态绑定,并要求我重复代码来设置每个状态的$ rootScopevariables。

使用$stateChangeSuccess

你可以把它放在一个指令中:

 app.directive('updateTitle', ['$rootScope', '$timeout', function($rootScope, $timeout) { return { link: function(scope, element) { var listener = function(event, toState) { var title = 'Default Title'; if (toState.data && toState.data.pageTitle) title = toState.data.pageTitle; $timeout(function() { element.text(title); }, 0, false); }; $rootScope.$on('$stateChangeSuccess', listener); } }; } ]); 

和:

 <title update-title></title> 

演示: http : //run.plnkr.co/8tqvzlCw62Tl7t4j/#/home

代码: http : //plnkr.co/edit/XO6RyBPURQFPodoFdYgX?p=preview

即使使用$stateChangeSuccess$timeout也需要历史logging$stateChangeSuccess正确的,至less在我testing过自己的时候。


编辑:2014年11月24日 – 声明的方法:

 app.directive('title', ['$rootScope', '$timeout', function($rootScope, $timeout) { return { link: function() { var listener = function(event, toState) { $timeout(function() { $rootScope.title = (toState.data && toState.data.pageTitle) ? toState.data.pageTitle : 'Default title'; }); }; $rootScope.$on('$stateChangeSuccess', listener); } }; } ]); 

和:

 <title>{{title}}</title> 

演示: http : //run.plnkr.co/d4s3qBikieq8egX7/#/credits

代码: http : //plnkr.co/edit/NpzQsxYGofswWQUBGthR?p=preview

已经有另外一种方法来结合大部分的答案。 我知道这已经回答了,但我想展示我用ui-routerdynamic更改页面标题的方式。

如果你看看ui-router 示例应用程序 ,他们使用angular .run块将$ statevariables添加到$ rootScope中。

 // It's very handy to add references to $state and $stateParams to the $rootScope // so that you can access them from any scope within your applications. // For example, <li ng-class="{ active: $state.includes('contacts.list') }"> // will set the <li> to active whenever 'contacts.list' or one of its // decendents is active. .run([ '$rootScope', '$state', '$stateParams', function ($rootScope, $state, $stateParams) { $rootScope.$state = $state; $rootScope.$stateParams = $stateParams; }]) 

有了这个定义,你可以很容易地dynamic更新你的页面标题与你已经发布,但修改为使用定义的状态:

用相同的方法设置状态:

 .state('home', { url: '/home', templateUrl : 'views/home.html', data : { pageTitle: 'Home' } }) 

但是编辑html有点…

 <title ng-bind="$state.current.data.pageTitle"></title> 

我不能说这比以前的答案更好,但对我来说更容易理解和实施。 希望这可以帮助别人!

angular-ui-router-title插件可以很容易地将页面标题更新为基于当前状态的静态dynamic值。 它也正确地与浏览器历史logging一起工作。

$stateChangeSuccess现在在UI-Router 1.x中不推荐使用,默认情况下禁用。 您现在需要使用新的$transition服务。

一旦了解$transition工作原理,解决scheme就不是太难。 我从@troig得到了一些帮助 ,理解这一切。 这是我想出的更新标题。

把它放在你的Angular 1.6应用程序中。 请注意,我正在使用ECMAScript 6语法; 如果你不是,你需要例如改变let var

 .run(function($transitions, $window) { $transitions.onSuccess({}, (transition) => { let title = transition.to().title; if (title) { if (title instanceof Function) { title = title.call(transition.to(), transition.params()); } $window.document.title = title; } }); 

然后只需添加一个titlestring到你的状态:

 $stateProvider.state({ name: "foo", url: "/foo", template: "<foo-widget layout='row'/>", title: "Foo Page"" }); 

这将使标题中出现“Foo Page”字样。 (如果一个状态没有标题,那么页面标题将不会被更新,如果状态没有显示,就更新上面的代码来提供一个默认的标题。

该代码还允许您使用titlefunction。 用来调用函数的是状态本身,其中一个参数是状态参数,如下例所示:

 $stateProvider.state({ name: "bar", url: "/bar/{code}", template: "<bar-widget code='{{code}}' layout='row'/>", title: function(params) { return `Bar Code ${params.code}`; } }); 

对于将显示“Bar Code 123”作为页面标题的URLpath/bar/code/123请注意,我使用ECMAScript 6语法来格式化string并提取params.code

如果有时间的人会把这样的东西写入指令并发布给大家使用,那将会很好。

将$ state附加到$ rootcope以在应用程序中的任何位置使用。

 app.run(['$rootScope', '$state', '$stateParams', function ($rootScope, $state, $stateParams) { // It's very handy to add references to $state and $stateParams to the $rootScope // so that you can access them from any scope within your applications.For example, // <li ng-class="{ active: $state.includes('contacts.list') }"> will set the <li> // to active whenever 'contacts.list' or one of its decendents is active. $rootScope.$state = $state; $rootScope.$stateParams = $stateParams; } ] ) 
 <title ng-bind="$state.current.name + ' - ui-router'">about - ui-router</title> 

我发现这种方式非常简单:

  .state('app.staff.client', { url: '/client/mine', title: 'My Clients'}) 

然后在我的HTML这样的:

 <h3>{{ $state.current.title }}</h3> 

我正在使用ngMeta ,它不仅适用于设置页面标题而且也适用于描述。 它可以让你为每个状态设置一个特定的标题/描述,缺省的标题/描述没有被指定,以及默认的标题后缀(即“| MySiteName”)和作者值。

 $stateProvider .state('home', { url: '/', templateUrl: 'views/home.html', controller: 'HomeController', meta: { 'title': 'Home', 'titleSuffix': ' | MySiteName', 'description': 'This is my home page description lorem ipsum.' }, }) 

你真的很接近你的第一个答案/问题。 将您的标题添加为数据对象:

 .state('home', { url: '/home', templateUrl : 'views/home.html', data : { pageTitle: 'Home' } }) 

在index.html中直接将数据绑定到页面标题:

 <title data-ng-bind="$state.current.data.pageTitle + ' - Optional text'">Failsafe text</title> 

只需更新window.document.title:

 .state('login', { url: '/login', templateUrl: "/Login", controller: "loginCtrl", onEnter: function($window){$window.document.title = "App Login"; } }) 

这种方式“ng-app”不需要移动到HTML标签,可以保持在主体或更低。

我结束了Martin和tasseKATT的答案 – 简单而没有任何模板相关的东西:

 $rootScope.$on("$stateChangeSuccess", function (event, toState) { $timeout(function () { // Needed to ensure the title is changed *after* the url so that history entries are correct. $window.document.title = toState.name; }); }); 

为什么不只是:

 $window.document.title = 'Title'; 

更新:完整的指令代码

 var DIRECTIVE = 'yourPageTitle'; yourPageTitle.$inject = ['$window']; function yourPageTitle($window: ng.IWindowService): ng.IDirective { return { link: (scope, element, attrs) => { attrs.$observe(DIRECTIVE, (value: string) => { $window.document.title = value; }); } } } directive(DIRECTIVE, yourPageTitle); 

然后在每一页你只需要包含这个指令:

 <section your-page-title="{{'somePage' | translate}}"> 

如果你使用ES6,这工作得很好:)。

 class PageTitle { constructor($compile, $timeout) { this.restrict = 'A'; this._$compile = $compile; this.$timeout = $timeout; } compile(element) { return this.link.bind(this); } link(scope, element, attrs, controller) { let defaultTitle = attrs.pageTitle ? attrs.pageTitle : "My Awesome Sauce Site"; let listener = function(event, toState) { let title = defaultTitle; if (toState.data && toState.data.title) title = toState.data.title + ' | ' + title; $('html head title').text(title); }; scope.$on('$stateChangeStart', listener); } } export function directiveFactory($compile) { return new PageTitle($compile); } directiveFactory.injections = ['$compile', '$timeout']; export default PageTitle; 

也许你可以试试这个指令。

https://github.com/afeiship/angular-dynamic-title

这是一个例子:

HTML:

 <title dynamic-title>Title</title> <a href="javascript:;" ui-sref="state1">State1 page</a> <a href="javascript:;" ui-sref="state2">State2 page</a> 

JavaScript的:

 var TestModule = angular.module('TestApp', ['ui.router','nx.widget']) .config(function ($stateProvider, $urlRouterProvider) { // // For any unmatched url, redirect to /state1 $urlRouterProvider.otherwise("/state1"); // // Now set up the states $stateProvider .state('state1', { url: "/state1", templateUrl: "partials/state1.html", data:{ pageTitle:'State1 page title11111' } }) .state('state2', { url: "/state2", templateUrl: "partials/state2.html",data:{ pageTitle:'State2 page title222222' } }); }) .controller('MainCtrl', function ($scope) { console.log('initial ctrl!'); });