web-dev-qa-db-fra.com

Définir le titre de la page en utilisant UI-Router

Je migre mon application basée sur AngularJS pour utiliser ui-router au lieu du routage intégré. Je l'ai configuré comme indiqué ci-dessous

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

Comment utiliser la variable pageTitle pour définir dynamiquement le titre de la page? En utilisant le routage intégré, je pourrais faire

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

puis liez la variable en HTML comme indiqué ci-dessous

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

Existe-t-il un événement similaire auquel je peux participer en utilisant ui-router? J'ai remarqué qu'il existe des fonctions 'onEnter' et 'onExit' mais elles semblent liées à chaque état et m'obligeront à répéter le code pour définir la variable $ rootScope pour chaque état.

100
user1625066

Utilisation $stateChangeSuccess.

Vous pouvez le mettre dans une directive:

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

Et:

<title update-title></title>

Démo: http://run.plnkr.co/8tqvzlCw62Tl7t4j/#/home

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

Même avec $stateChangeSuccess le $timeout Il a été nécessaire que l'historique soit correct, du moins lorsque je me suis testé.


Edit: 24 nov. 2014 - Approche déclarative:

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

Et:

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

Démo: http://run.plnkr.co/d4s3qBikieq8egX7/#/credits

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

107
tasseKATT

Il existe un autre moyen de le faire en combinant déjà la plupart des réponses ici. Je sais que cela a déjà été répondu, mais je voulais montrer la façon dont je change dynamiquement le titre des pages avec ui-router.

Si vous jetez un oeil à ui-router exemple d'application , ils utilisent le bloc angular . Run pour ajouter la variable $ state à $ 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;
}])

Avec ceci défini, vous pouvez ensuite facilement mettre à jour dynamiquement le titre de votre page avec ce que vous avez posté mais modifié pour utiliser l'état défini:

Configurez l'état de la même manière:

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

Mais éditez un peu le code HTML ...

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

Je ne peux pas dire que c'est mieux que les réponses précédentes ... mais que c'était plus facile pour moi de comprendre et de mettre en œuvre. J'espère que cela aide quelqu'un!

91
cwbutler

Le plugin angular-ui-router-title facilite la mise à jour du titre de la page en un statique ou dynamique valeur basée sur l'état actuel. Cela fonctionne correctement avec l'historique du navigateur, aussi.

17
Stepan Riha

$stateChangeSuccess est maintenant obsolète dans UI-Router 1.x et désactivé par défaut. Vous devez maintenant utiliser le nouveau $transition un service.

Une solution n’est pas trop difficile une fois que vous avez compris comment $transition travaux. J'ai quelques aide de @troig pour tout comprendre. Voici ce que je suis venu avec pour mettre à jour le titre.

Mettez ceci dans votre Angular 1.6 application. Notez que j'utilise la syntaxe ECMAScript 6; si vous ne l'êtes pas, vous devrez par exemple changer 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;
        }
    });

Ensuite, ajoutez simplement une chaîne title à votre état:

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

Cela fera apparaître les mots "Foo Page" dans le titre. (Si un état n'a pas de titre, le titre de la page ne sera pas mis à jour. Il serait simple de mettre à jour le code ci-dessus pour fournir un titre par défaut si un état ne l'indique pas.)

Le code vous permet également d'utiliser une fonction pour title. Le this utilisé pour appeler la fonction sera l'état lui-même, et l'un des arguments sera les paramètres d'état, comme dans l'exemple suivant:

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

Pour le chemin de l'URL /bar/code/123 qui afficherait "Code à barres 123" comme titre de la page. Notez que j'utilise la syntaxe ECMAScript 6 pour formater la chaîne et extraire params.code.

Ce serait bien si quelqu'un qui en avait le temps mettrait quelque chose dans ce sens dans une directive et la publierait pour que tout le monde puisse l'utiliser.

13
Garret Wilson

J'ai trouvé de cette façon vraiment facile:

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

puis dans mon code HTML comme ceci:

<h3>{{ $state.current.title }}</h3>
5
Mike Rouse

Attacher $ state à $ rootscope à utiliser n'importe où dans l'application.

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>
5
simbu

Il suffit de mettre à jour window.document.title:

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

De cette façon, 'ng-app' n'a pas besoin de passer à la balise HTML et peut rester sur le corps ou plus bas.

3
getsetbro

J'utilise ngMeta , ce qui fonctionne bien non seulement pour définir le titre de la page, mais également pour les descriptions. Il vous permet de définir un titre/une description spécifique pour chaque état, les valeurs par défaut pour lesquelles un titre/une description n'est pas spécifié, ainsi que les suffixes de titre par défaut (c'est-à-dire '| MySiteName') et la valeur de l'auteur.

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

Vous êtes vraiment très proche de votre première réponse/question. Ajoutez votre titre en tant qu'objet de données:

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

Dans votre index.html, liez les données directement au titre de la page:

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

Je me suis retrouvé avec cette combinaison de réponses de Martin et de tasseKATT - simple et sans aucun élément lié au modèle:

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

Pourquoi pas simplement:

$window.document.title = 'Title';

PDATE: Code de directive complète

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

Ensuite, dans chaque page, vous incluez simplement cette directive:

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

Peut-être que vous pouvez essayer cette directive.

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

Voici l'exemple:

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

Si vous utilisez ES6, cela fonctionne très 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;
0
TGarrett

Pour les versions mises à jour de UI-Router 1.0.0+, ( https://ui-router.github.io/guide/ng1/migrate-to-1_ )

Se référer au code suivant

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

Ajoutez ce qui suit à votre index.html:

<title page-title ng-bind="page_title"></title>
0
Palsri