Establecer el título de la página usando UI-Router

Estoy migrando mi aplicación AngularJS para usar el enrutador ui en lugar del enrutamiento integrado. Lo tengo configurado como se muestra a continuación

.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' } }) }); 

¿Cómo puedo usar la variable pageTitle para establecer dinámicamente el título de la página? Usando el enrutamiento integrado, podría hacer

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

y luego enlazar la variable en HTML como se muestra a continuación

  

¿Hay algún evento similar al que pueda conectarme usando ui-router? Noté que hay funciones ‘onEnter’ y ‘onExit’, pero parecen estar vinculadas a cada estado y requieren que repita el código para establecer la variable $ rootScope para cada estado.

Use $stateChangeSuccess .

Puedes ponerlo en una directiva:

 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); } }; } ]); 

Y:

  

Demostración: http://run.plnkr.co/8tqvzlCw62Tl7t4j/#/home

Código: http://plnkr.co/edit/XO6RyBPURQFPodoFdYgX?p=preview

Incluso con $stateChangeSuccess se ha necesitado $timeout para que el historial sea correcto, al menos cuando me he probado a mí mismo.


Edición: 24 de noviembre de 2014 – Enfoque declarativo:

 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); } }; } ]); 

Y:

 {{title}} 

Demostración: http://run.plnkr.co/d4s3qBikieq8egX7/#/credits

Código: http://plnkr.co/edit/NpzQsxYGofswWQUBGthR?p=preview

Hay otra forma de hacerlo combinando la mayoría de las respuestas aquí. Sé que esto ya está respondido, pero quería mostrar la forma en que cambio dinámicamente los títulos de las páginas con ui-router.

Si echas un vistazo a la aplicación de ejemplo ui-router, usan el bloque .run angular para agregar la variable $ state a $ 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, 
  • // will set the
  • 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; }])
  • Con esto definido, puede actualizar dinámicamente el título de su página con lo que ha publicado pero modificado para usar el estado definido:

    Configure el estado de la misma manera:

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

    Pero edita el html un poco …

      

    No puedo decir que esto sea mejor que las respuestas anteriores … pero fue más fácil para mí entenderlo e implementarlo. ¡Espero que esto ayude a alguien!

    El complemento angular-ui-router-title hace que sea fácil actualizar el título de la página a un valor estático o dynamic basado en el estado actual. También funciona correctamente con el historial del navegador.

    $stateChangeSuccess ahora está en desuso en UI-Router 1.xy deshabilitado de manera predeterminada. Ahora deberá usar el nuevo servicio de $transition .

    Una solución no es demasiado difícil una vez que comprenda cómo funciona $transition . Obtuve ayuda de @troig para entenderlo todo. Esto es lo que se me ocurrió para actualizar el título.

    Pon esto en tu aplicación Angular 1.6. Tenga en cuenta que estoy usando la syntax de ECMAScript 6; si no lo eres, necesitarás, por ejemplo, cambiar a 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; } }); 

    Luego solo agrega una cadena de title a tu estado:

     $stateProvider.state({ name: "foo", url: "/foo", template: "", title: "Foo Page"" }); 

    Eso hará que las palabras “Foo Page” aparezcan en el título. (Si un estado no tiene título, el título de la página no se actualizará. Sería algo sencillo actualizar el código anterior para proporcionar un título predeterminado si un estado no lo indica).

    El código también le permite usar una función para el title . this solía llamar a la función será el estado en sí, y el único argumento serán los parámetros de estado, como este ejemplo:

     $stateProvider.state({ name: "bar", url: "/bar/{code}", template: "", title: function(params) { return `Bar Code ${params.code}`; } }); 

    Para la ruta URL /bar/code/123 que mostraría “Código de barras 123” como título de la página. Tenga en cuenta que estoy usando la syntax de ECMAScript 6 para formatear la cadena y extraer params.code .

    Sería bueno que alguien que tenía el tiempo pusiera algo así en una directiva y lo publicara para que todos lo usen.

    Adjuntando $ state a $ rootscope para usar en cualquier lugar de la aplicación.

     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, // 
  • will set the
  • // to active whenever 'contacts.list' or one of its decendents is active. $rootScope.$state = $state; $rootScope.$stateParams = $stateParams; } ] )
  •  about - ui-router 

    Me pareció muy fácil de esta manera :

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

    y luego en mi HTML así:

     

    {{ $state.current.title }}

    Simplemente actualice window.document.title:

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

    De esta forma, ‘ng-app’ no necesita pasar a la etiqueta HTML y puede permanecer en el cuerpo o más abajo.

    Estoy usando ngMeta , que funciona bien no solo para configurar el título de la página, sino también las descripciones. Le permite establecer un título / descripción específica para cada estado, los valores predeterminados para cuando no se especifica un título / descripción, así como los sufijos de título predeterminados (es decir, ‘| MySiteName’) y el valor del autor.

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

    En realidad estás muy cerca de tu primera respuesta / pregunta. Agregue su título como un objeto de datos:

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

    En su index.html vincula los datos directamente al título de la página:

     Failsafe text 

    Terminé con esta combinación de las respuestas de Martin y tasseKATT: simple y sin ningún elemento relacionado con la plantilla:

     $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; }); }); 

    ¿Por qué no solo?

     $window.document.title = 'Title'; 

    ACTUALIZACIÓN: Código de directiva completa

     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); 

    Luego, en cada página, simplemente incluirías esta directiva:

     

    Si está utilizando ES6, esto funciona bien :).

     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; 

    Tal vez puedas probar esta directiva.

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

    Aquí está el ejemplo:

    html:

     Title State1 page State2 page 

    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!'); }); 

    Para las versiones actualizadas de UI-Router 1.0.0+, ( https://ui-router.github.io/guide/ng1/migrate-to-1_0 )

    Consulte el siguiente código

     app.directive('pageTitle', [ '$rootScope', '$timeout', '$transitions', function($rootScope, $timeout,$transitions) { return { restrict: 'A', link: function() { var listener = function($transitions) { var default_title = "DEFAULT_TITLE"; $timeout(function() { $rootScope.page_title = ($transitions.$to().data && $transitions.$to().data.pageTitle) ? default_title + ' - ' + $transitions.$to().data.pageTitle : default_title; }); }; $transitions.onSuccess({ }, listener); } } } ])