Estou migrando meu aplicativo baseado em AngularJS para usar o roteador-ui em vez do roteamento interno. Eu tenho configurado conforme mostrado abaixo
.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' } }) });
Como posso usar a variável pageTitle para definir dinamicamente o título da página? Usando o roteamento interno, eu poderia fazer
$rootScope.$on("$routeChangeSuccess", function(currentRoute, previousRoute){ $rootScope.pageTitle = $route.current.data.pageTitle; });
e depois ligar a variável em HTML como mostrado abaixo
Existe um evento semelhante que eu possa ligar usando o ui-roteador? Notei que existem funções ‘onEnter’ e ‘onExit’, mas elas parecem estar ligadas a cada estado e exigirão que eu repita o código para definir a variável $ rootScope para cada estado.
Use $stateChangeSuccess
.
Você pode colocá-lo em uma diretiva:
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); } }; } ]);
E:
Demonstração: http://run.plnkr.co/8tqvzlCw62Tl7t4j/#/home
Código: http://plnkr.co/edit/XO6RyBPURQFPodoFdYgX?p=preview
Mesmo com $stateChangeSuccess
o $timeout
foi necessário para que o histórico seja correto, pelo menos quando eu mesmo testei.
Edit: 24 de novembro de 2014 – abordagem declarativa:
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); } }; } ]);
E:
{{title}}
Demonstração: http://run.plnkr.co/d4s3qBikieq8egX7/#/credits
Existe uma outra maneira de fazer isso, combinando a maioria das respostas aqui já. Eu sei que isso já está respondido, mas eu queria mostrar como altero dinamicamente os títulos das páginas com o roteador-ui.
Se você der uma olhada no aplicativo de amostra do ui-roteador, eles usarão o bloco .run angular para adicionar a variável $ state ao $ 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; }])
Com isso definido, você pode atualizar dinamicamente o título da sua página com o que você postou, mas modificou para usar o estado definido:
Configure o estado da mesma maneira:
.state('home', { url: '/home', templateUrl : 'views/home.html', data : { pageTitle: 'Home' } })
Mas edite o html um pouco …
Eu não posso dizer que isso é melhor do que as respostas antes … mas foi mais fácil para eu entender e implementar. Espero que isso ajude alguém!
O plug – in angular-ui-router-title facilita a atualização do título da página para um valor estático ou dynamic com base no estado atual. Funciona corretamente com o histórico do navegador também.
$stateChangeSuccess
agora está obsoleto no roteador de UI 1.x e desabilitado por padrão. Agora você precisará usar o novo serviço de $transition
.
Uma solução não é muito difícil quando você entende como funciona a $transition
. Eu tenho ajuda do @troig para entender tudo. Aqui está o que eu inventei para atualizar o título.
Coloque isso na sua aplicação Angular 1.6. Note que estou usando a syntax do ECMAScript 6; se você não for, você precisará, por exemplo, alterar o let
para 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; } });
Em seguida, basta adicionar uma string de title
ao seu estado:
$stateProvider.state({ name: "foo", url: "/foo", template: " ", title: "Foo Page"" });
Isso fará com que as palavras “Foo Page” apareçam no título. (Se um estado não tiver título, o título da página não será atualizado. Seria uma coisa simples atualizar o código acima para fornecer um título padrão se um estado não indicar um.)
O código também permite que você use uma function para title
. O usado para chamar a function será o próprio estado e o argumento será os parâmetros de estado, como neste exemplo:
$stateProvider.state({ name: "bar", url: "/bar/{code}", template: " ", title: function(params) { return `Bar Code ${params.code}`; } });
Para o caminho de URL /bar/code/123
que mostraria “Código de Barras 123” como o título da página. Note que estou usando a syntax ECMAScript 6 para formatar a string e extrair params.code
.
Seria bom se alguém que tivesse tempo colocasse algo assim em uma diretiva e a publicasse para todo mundo usar.
Anexando $ state a $ rootscope para usar em qualquer lugar do aplicativo.
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
Eu achei isso muito fácil:
.state('app.staff.client', { url: '/client/mine', title: 'My Clients'})
e então no meu HTML assim:
{{ $state.current.title }}
Apenas atualize window.document.title:
.state('login', { url: '/login', templateUrl: "/Login", controller: "loginCtrl", onEnter: function($window){$window.document.title = "App Login"; } })
Dessa forma, o ‘ng-app’ não precisa passar para a tag HTML e pode permanecer no corpo ou menos.
Estou usando o ngMeta , que funciona bem não só para definir o título da página, mas também as descrições. Ele permite que você defina um título / descrição específico para cada estado, padrões para quando um título / descrição não é especificado, assim como sufixos de títulos padrão (ou seja, ‘| MySiteName’) e valor de 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.' }, })
Você está realmente perto de sua primeira resposta / pergunta. Adicione seu título como um object de dados:
.state('home', { url: '/home', templateUrl : 'views/home.html', data : { pageTitle: 'Home' } })
Em seu index.html, vincule os dados diretamente ao título da página:
Failsafe text
Acabei com essa combinação de respostas de Martin e tasseKATT – simples e sem qualquer material relacionado a modelos:
$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 que não apenas:
$window.document.title = 'Title';
ATUALIZAÇÃO: Código da Diretiva 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);
Então, em todas as páginas, você includeia essa diretiva:
Se você estiver usando ES6, isso funciona muito bem :).
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;
Talvez você possa tentar esta diretiva.
https://github.com/afeiship/angular-dynamic-title
Title State1 page State2 page
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 versões atualizadas do UI-Router 1.0.0+, ( https://ui-router.github.io/guide/ng1/migrate-to-1_0 )
Consulte o seguinte 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); } } } ])