Estou usando a ng-view para incluir visualizações parciais do AngularJS e quero atualizar o título da página e as tags de cabeçalho h1 com base na visualização incluída. Porém, eles estão fora do escopo dos controladores de exibição parcial e, portanto, não consigo descobrir como vinculá-los ao conjunto de dados nos controladores.
Se fosse o ASP.NET MVC, você poderia usar o @ViewBag para fazer isso, mas não sei o equivalente no AngularJS. Eu pesquisei sobre serviços compartilhados, eventos etc., mas ainda não consigo fazê-lo funcionar. Qualquer maneira de modificar meu exemplo para que ele funcione seria muito apreciada.
Meu HTML:
<html data-ng-app="myModule">
<head>
<!-- include js files -->
<title><!-- should changed when ng-view changes --></title>
</head>
<body>
<h1><!-- should changed when ng-view changes --></h1>
<div data-ng-view></div>
</body>
</html>
Meu JavaScript:
var myModule = angular.module('myModule', []);
myModule.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/test1', {templateUrl: 'test1.html', controller: Test1Ctrl}).
when('/test2', {templateUrl: 'test2.html', controller: Test2Ctrl}).
otherwise({redirectTo: '/test1'});
}]);
function Test1Ctrl($scope, $http) { $scope.header = "Test 1";
/* ^ how can I put this in title and h1 */ }
function Test2Ctrl($scope, $http) { $scope.header = "Test 2"; }
Respostas:
Você pode definir o controlador no
<html>
nível.Você cria o serviço:
Page
e modifica a partir dos controladores.Injete
Page
e chame 'Page.setTitle ()' dos controladores.Aqui está o exemplo concreto: http://plnkr.co/edit/0e7T6l
fonte
$rootScope
vez de criar um controlador adicional.Acabei de descobrir uma ótima maneira de definir o título da sua página se você estiver usando o roteamento:
JavaScript:
HTML:
Editar : usando o
ng-bind
atributo em vez de curvas,{{}}
para que não apareçam no carregamentofonte
title = "Blog"
mas nãotitle = '{{"Blog post " + post.title}}'
.current.title
tambémcurrent.$route
o código antigo e estava funcionando. Com a atualização, o dobro de $ na rota é necessário.current.$$route
'/Product/:id'
. Existe alguma maneira de ter o:id
valor com este método? Eu tentei,title: function(params){return params.id;}
mas não funciona ... Talvez usandoresolve
?Observe que você também pode definir o título diretamente com javascript, ou seja,
Isso não possui ligação de dados, mas é suficiente quando a inserção
ng-app
da<html>
tag é problemática. (Por exemplo, usando modelos JSP em que<head>
é definido exatamente em um local, você possui mais de um aplicativo.)fonte
Declarar
ng-app
sobre ohtml
elemento fornece escopo raiz parahead
ebody
.Portanto, em seu controlador, injete
$rootScope
e defina uma propriedade de cabeçalho sobre isso:e na sua página:
fonte
document.title = "App"
;O módulo angularjs-viewhead mostra um mecanismo para definir o título por visualização usando apenas uma diretiva personalizada.
Ele pode ser aplicado a um elemento de exibição existente cujo conteúdo já é o título da exibição:
... ou pode ser usado como um elemento independente. Nesse caso, o elemento ficará invisível no documento renderizado e será usado apenas para definir o título da visualização:
O conteúdo desta diretiva é disponibilizado no escopo raiz como
viewTitle
, para que possa ser usado no elemento title, como qualquer outra variável:Também pode ser usado em qualquer outro local que possa "ver" o escopo raiz. Por exemplo:
Esta solução permite que o título seja definido através do mesmo mecanismo usado para controlar o restante da apresentação: Modelos AngularJS. Isso evita a necessidade de desorganizar os controladores com essa lógica de apresentação. O controlador precisa disponibilizar todos os dados que serão usados para informar o título, mas o modelo faz a determinação final de como apresentá-lo e pode usar a interpolação de expressão e os filtros para vincular os dados do escopo normalmente.
(Isenção de responsabilidade: sou o autor deste módulo, mas o referencio aqui apenas na esperança de que ajude alguém a resolver esse problema.)
fonte
Aqui está uma solução adaptada que funciona para mim e que não requer injeção de $ rootScope nos controladores para definir títulos de página específicos de recursos.
No modelo mestre:
Na configuração de roteamento:
E no bloco de corrida:
Finalmente no controlador:
fonte
$rootScope.page.setTitle(current.$$route.title || current.$$route.controller.replace('Ctrl', ''));
this.title = title.replace('<', '<').replace('>', '>').replace(' & ', ' & ') + ' | Site Name';
A solução da jkoreska é perfeita se você conhece os títulos de antemão, mas pode ser necessário definir o título com base nos dados obtidos de um recurso etc.
Minha solução requer um único serviço. Como o rootScope é a base de todos os elementos DOM, não precisamos colocar um controlador no elemento html como alguém mencionado
Page.js
index.jade
Todos os controladores que precisam alterar o título
fonte
{{title}}
usong-bind='title'
ng-bind
impede que a sintaxe pré-interpolada seja exibida antes que o título seja avaliado. +100Uma maneira limpa que permite definir dinamicamente título ou meta descrição. No exemplo, eu uso o ui-router, mas você pode usar o ngRoute da mesma maneira.
HTML:
fonte
Como alternativa, se você estiver usando o ui-router :
index.html
Encaminhamento
fonte
ui-router
atualização de URL e conteúdo com base no meu estado e não recebo erros ou avisos, mas não consigo acessar nenhuma parte do objeto de configuração do estado$state.current.[...]
. Qual versãoui-router
você usou para fazer isso?Solução personalizada baseada em eventos
Aqui está outra abordagem que não foi mencionada pelos outros aqui (no momento em que escrevo).
Você pode usar eventos personalizados da seguinte forma:
Essa abordagem tem a vantagem de não exigir que serviços extras sejam gravados e injetados em todos os controladores que precisam definir o título e também não (ab) usam o
$rootScope
. Ele também permite que você defina um título dinâmico (como no exemplo de código), o que não é possível usando atributos de dados personalizados no objeto de configuração do roteador (tanto quanto eu saiba).fonte
Para cenários em que você não possui um ngApp que contém a
title
tag, basta injetar um serviço nos controladores que precisam definir o título da janela.Exemplo de trabalho ... http://jsfiddle.net/8m379/1/
fonte
Se você não tem controle sobre o elemento title (como o formulário da web asp.net), aqui está algo que você pode usar
fonte
Maneira simples e suja usando
$rootScope
:Nos seus controladores, quando você tiver os dados necessários para criar o título, faça:
fonte
Nenhuma dessas respostas parecia intuitiva o suficiente, então criei uma pequena diretiva para fazer isso. Dessa maneira, você pode declarar o título na página, onde normalmente o faria, e também dinâmico.
É claro que você precisará alterar o nome do módulo para corresponder ao seu.
Para usá-lo, basta colocar isso na sua opinião, da mesma forma que faria com uma
<title>
tag comum :Você também pode incluir apenas texto sem formatação, caso não precise dinamicamente:
Como alternativa, você pode usar um atributo, para torná-lo mais amigável ao IE:
Você pode colocar o texto que desejar na tag, é claro, incluindo o código Angular. Neste exemplo, ele procurará
$scope.titleText
em qualquer controlador em que a tag de título personalizado esteja atualmente.Apenas certifique-se de não ter várias tags de título de página em sua página, ou elas serão prejudicadas.
Exemplo de plunker aqui http://plnkr.co/edit/nK63te7BSbCxLeZ2ADHV . Você precisará fazer o download do zip e executá-lo localmente para ver a alteração do título.
fonte
html
. Na minha diretiva, também injeto umapageTitlePrefix
constante opcional .Solução simplista para roteador-ui angular:
HTML:
Bloco App.js> myApp.config
App.js> myApp.run
fonte
Aqui está uma maneira diferente de fazer alterações de título. Talvez não seja tão escalável quanto uma função de fábrica (que poderia lidar com páginas ilimitadas), mas era mais fácil para mim entender:
No meu index.html, comecei assim:
Então eu fiz um parcial chamado "nav.html":
Então voltei para "index.html" e adicionei o nav.html usando ng-include e ng-view para minhas parciais:
Observe que ng-manto? Não tem nada a ver com esta resposta, mas oculta a página até terminar de carregar, com um toque agradável :) Aprenda como aqui: Angularjs - elementos ng-cloak / ng-show piscam
Aqui está o módulo básico. Coloquei-o em um arquivo chamado "app.js":
Se você olhar para o final do módulo, verá que tenho uma página de detalhes de bichos baseada em: id. É uma parte parcial usada na página Crispy Critters. [Corny, eu sei - talvez seja um site que celebra todos os tipos de nuggets de frango;) De qualquer forma, você pode atualizar o título quando um usuário clica em qualquer link, portanto, na minha página principal do Crispy Critters que leva à página de detalhes do bicho, é para onde a atualização do $ root.title iria, assim como você viu no nav.html acima:
Desculpe muito vento, mas eu prefiro um post que dê detalhes suficientes para colocá-lo em funcionamento. Observe que a página de exemplo nos documentos do AngularJS está desatualizada e mostra uma versão 0.9 do ng-bind-template. Você pode ver que não é tão diferente assim.
Pensamento tardio: você sabe disso, mas está aqui para mais alguém; na parte inferior do index.html, é necessário incluir o app.js no módulo:
fonte
Quando tive que resolver isso, não consegui colocar a tag
ng-app
na páginahtml
e resolvi-a com um serviço:fonte
Solução personalizada baseada em eventos inspirada em Michael Bromley
Não consegui fazê-lo funcionar com $ scope, então tentei com o rootScope, talvez um pouco mais sujo ... (especialmente se você fizer uma atualização na página que não registra o evento)
Mas eu realmente gosto da ideia de como as coisas são vagamente acopladas.
Estou usando o angularjs 1.6.9
index.run.js
anyController.controller.js
index.html
Está funcionando para mim :)
fonte
Enquanto outros podem ter métodos melhores, pude usar $ rootScope em meus controladores, pois cada uma das minhas visualizações / modelos possui um controlador distinto. Você precisará injetar o $ rootScope em cada controlador. Embora isso possa não ser o ideal, está funcionando para mim, então achei que deveria passar adiante. Se você inspecionar a página, ela adicionará a vinculação ng à tag title.
Controlador de exemplo:
Exemplo de cabeçalho Index.html:
Você também pode definir o pageTitle e o pageDescription para valores dinâmicos, como retornar dados de uma chamada REST:
Novamente, outras pessoas podem ter melhores idéias sobre como abordar isso, mas como estou usando uma pré-renderização, minhas necessidades estão sendo atendidas.
fonte
Obrigado a shoshyama por sua solução.
Eu pensei que não era tão limpo colocar um serviço diretamente no
$scope
, então aqui está minha pequena variação sobre isso: http://plnkr.co/edit/QJbuZZnZEDOBcYrJXWWsO controlador (que na resposta original me pareceu um pouco idiota) cria um objeto ActionBar, e este é inserido no $ scope.
O objeto é responsável por realmente consultar o serviço. Ele também oculta do escopo $ a chamada para definir o URL do modelo, que está disponível para outros controladores para definir o URL.
fonte
O Sr. Hash teve a melhor resposta até agora, mas a solução abaixo a torna ideal (para mim) adicionando os seguintes benefícios:
No roteador:
No bloco de execução:
fonte
A solução melhor e dinâmica que encontrei é usar $ watch para rastrear as alterações das variáveis e, em seguida, atualizar o título.
fonte