Estoy usando ng-view para incluir vistas parciales de AngularJS, y quiero actualizar el título de la página y las etiquetas de encabezado h1 en función de la vista incluida. Sin embargo, estos están fuera del alcance de los controladores de vista parcial, por lo que no puedo entender cómo vincularlos al conjunto de datos en los controladores.
Si fuera ASP.NET MVC, podría usar @ViewBag para hacer esto, pero no sé el equivalente en AngularJS. He buscado servicios compartidos, eventos, etc., pero todavía no puedo hacerlo funcionar. Cualquier forma de modificar mi ejemplo para que funcione sería muy apreciada.
Mi 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>
Mi 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"; }
Respuestas:
Puede definir el controlador en el
<html>
nivel.Usted crea servicio:
Page
y lo modifica desde los controladores.Inyecte
Page
y llame a 'Page.setTitle ()' desde los controladores.Aquí está el ejemplo concreto: http://plnkr.co/edit/0e7T6l
fuente
$rootScope
lugar de crear un controlador adicional.Acabo de descubrir una buena manera de configurar el título de tu página si estás usando enrutamiento:
JavaScript:
HTML:
Editar : usar el
ng-bind
atributo en lugar de curlies{{}}
para que no se muestren al cargarfuente
title = "Blog"
pero notitle = '{{"Blog post " + post.title}}'
.current.title
tambiéncurrent.$route
el código anterior y estaba funcionando. Con la actualización, se necesita el doble de $ en ruta.current.$$route
'/Product/:id'
. ¿Hay alguna forma de tener el:id
valor con este método? Lo intentétitle: function(params){return params.id;}
pero no funciona ... ¿Tal vez usandoresolve
?Tenga en cuenta que también puede establecer el título directamente con javascript, es decir,
Esto no tiene enlace de datos, pero es suficiente cuando poner
ng-app
la<html>
etiqueta es problemático. (Por ejemplo, usando plantillas JSP donde<head>
se define exactamente en un lugar, sin embargo, tiene más de una aplicación).fuente
La declaración
ng-app
sobre elhtml
elemento proporciona un alcance raíz tanto para elhead
ybody
.Por lo tanto, en su controlador, inyecte
$rootScope
y establezca una propiedad de encabezado en esto:y en tu página:
fuente
document.title = "App"
;El módulo angularjs-viewhead muestra un mecanismo para establecer el título por vista utilizando solo una directiva personalizada.
Se puede aplicar a un elemento de vista existente cuyo contenido ya es el título de la vista:
... o puede usarse como un elemento independiente, en cuyo caso el elemento será invisible en el documento renderizado y solo se usará para establecer el título de la vista:
El contenido de esta directiva está disponible en el ámbito raíz como
viewTitle
, por lo que puede usarse en el elemento de título como cualquier otra variable:También se puede usar en cualquier otro lugar que pueda "ver" el alcance raíz. Por ejemplo:
Esta solución permite establecer el título mediante el mismo mecanismo que se utiliza para controlar el resto de la presentación: plantillas AngularJS. Esto evita la necesidad de saturar los controladores con esta lógica de presentación. El controlador debe poner a disposición cualquier dato que se utilizará para informar el título, pero la plantilla toma la determinación final sobre cómo presentarlo y puede usar la interpolación de expresión y los filtros para enlazar a los datos del alcance de forma normal.
(Descargo de responsabilidad: soy el autor de este módulo, pero lo estoy haciendo referencia aquí solo con la esperanza de que ayude a alguien más a resolver este problema).
fuente
Aquí hay una solución adaptada que funciona para mí que no requiere la inyección de $ rootScope en los controladores para configurar títulos de página específicos de recursos.
En la plantilla maestra:
En la configuración de enrutamiento:
Y en el bloque de ejecución:
Finalmente en el controlador:
fuente
$rootScope.page.setTitle(current.$$route.title || current.$$route.controller.replace('Ctrl', ''));
this.title = title.replace('<', '<').replace('>', '>').replace(' & ', ' & ') + ' | Site Name';
La solución de jkoreska es perfecta si conoce los títulos de antemano, pero es posible que deba establecer el título en función de los datos que obtiene de un recurso, etc.
Mi solución requiere un solo servicio. Como rootScope es la base de todos los elementos DOM, no necesitamos poner un controlador en el elemento html como alguien mencionó
Page.js
index.jade
Todos los controladores que necesitan cambiar de título.
fuente
{{title}}
su lugar useng-bind='title'
ng-bind
evita que la sintaxis pre-interpolada se muestre antes de que el título realmente se evalúe. +100Una forma limpia que permite establecer dinámicamente el título o la meta descripción. En el ejemplo uso ui-router pero puedes usar ngRoute de la misma manera.
HTML:
fuente
Alternativamente, si está utilizando ui-router :
index.html
Enrutamiento
fuente
ui-router
actualizaciones de URL y contenido según mi estado y no recibo errores ni advertencias, pero parece que no puedo acceder a ninguna parte del objeto de configuración de estado$state.current.[...]
. ¿Qué versión deui-router
usaste para hacer esto?Solución personalizada basada en eventos
Aquí hay otro enfoque que no ha sido mencionado por los demás aquí (a partir de este escrito).
Puede usar eventos personalizados de esta manera:
Este enfoque tiene la ventaja de no requerir que se escriban servicios adicionales y luego se inyecten en cada controlador que necesita establecer el título, y tampoco (ab) usa el
$rootScope
. También le permite establecer un título dinámico (como en el ejemplo de código), que no es posible utilizando atributos de datos personalizados en el objeto de configuración del enrutador (hasta donde yo sé al menos).fuente
Para escenarios en los que no tiene una ngApp que contiene la
title
etiqueta, simplemente inyecte un servicio a los controladores que necesitan establecer el título de la ventana.Ejemplo de trabajo ... http://jsfiddle.net/8m379/1/
fuente
Si no tiene control sobre el elemento de título (como el formulario web asp.net), aquí hay algo que puede usar
fuente
Manera simple y sucia usando
$rootScope
:En sus controladores, cuando tenga los datos necesarios para crear el título, haga lo siguiente:
fuente
Ninguna de estas respuestas parecía lo suficientemente intuitiva, así que creé una pequeña directiva para hacer esto. De esta manera, puede declarar el título en la página, donde normalmente lo haría, y también le permite ser dinámico.
Por supuesto, deberá cambiar el nombre del módulo para que coincida con el suyo.
Para usarlo, simplemente arroje esto a su vista, como lo haría con una
<title>
etiqueta normal :También puede incluir texto sin formato si no lo necesita dinámicamente:
Alternativamente, puede usar un atributo para hacerlo más amigable con IE:
Por supuesto, puede poner el texto que desee en la etiqueta, incluido el código angular. En este ejemplo, buscará
$scope.titleText
en cualquier controlador en el que se encuentre actualmente la etiqueta de título personalizado.Solo asegúrate de no tener varias etiquetas de título de página en tu página, o se golpearán entre sí.
Ejemplo de Plunker aquí http://plnkr.co/edit/nK63te7BSbCxLeZ2ADHV . Tendrá que descargar el zip y ejecutarlo localmente para ver el cambio de título.
fuente
html
. En mi directiva también inyecto unapageTitlePrefix
constante opcional .Solución simplista para angular-ui-router:
HTML:
App.js> bloque myApp.config
App.js> myApp.run
fuente
Aquí hay una forma diferente de hacer cambios en el título. Tal vez no sea tan escalable como una función de fábrica (que posiblemente podría manejar páginas ilimitadas), pero me fue más fácil de entender:
En mi index.html comencé así:
Luego hice un parcial llamado "nav.html":
Luego volví a "index.html" y agregué el nav.html usando ng-include y ng-view para mis parciales:
¿Te das cuenta de que ng-cloak? No tiene nada que ver con esta respuesta, pero oculta la página hasta que termine de cargarse, un toque agradable :) Aprenda cómo aquí: Angularjs - parpadean los elementos ng-cloak / ng-show
Aquí está el módulo básico. Lo puse en un archivo llamado "app.js":
Si mira hacia el final del módulo, verá que tengo una página de detalles de criaturas basada en: id. Es un parcial que se usa desde la página Crispy Critters. [Corny, lo sé, tal vez es un sitio que celebra todo tipo de nuggets de pollo;) De todos modos, puedes actualizar el título cuando un usuario hace clic en cualquier enlace, así que en mi página principal de Crispy Critters que lleva a la página de detalles de criaturas, ahí es donde iría la actualización de $ root.title, tal como viste en el nav.html anterior:
Lo siento mucho viento, pero prefiero una publicación que brinde suficientes detalles para ponerla en marcha. Tenga en cuenta que la página de ejemplo en los documentos de AngularJS está desactualizada y muestra una versión 0.9 de ng-bind-template. Puedes ver que no es muy diferente.
Pensamiento posterior: sabes esto pero está aquí para cualquier otra persona; en la parte inferior de index.html, uno debe incluir app.js con el módulo:
fuente
Cuando tuve que resolver esto, no pude colocarlo
ng-app
en lahtml
etiqueta de la página , así que lo resolví con un servicio:fuente
Solución personalizada basada en eventos inspirada en Michael Bromley
No pude hacerlo funcionar con $ scope, así que intenté con rootScope, tal vez un poco más sucio ... (especialmente si hace una actualización en la página que no registra el evento)
Pero realmente me gusta la idea de cómo las cosas están unidas libremente.
Estoy usando angularjs 1.6.9
index.run.js
anyController.controller.js
index.html
Me está funcionando :)
fuente
Mientras que otros pueden tener mejores métodos, pude usar $ rootScope en mis controladores, ya que cada una de mis vistas / plantillas tiene un controlador distinto. Deberá inyectar $ rootScope en cada controlador. Si bien esto puede no ser ideal, está funcionando para mí, así que pensé que debería pasarlo. Si inspecciona la página, agrega el enlace ng a la etiqueta del título.
Controlador de ejemplo:
Ejemplo de encabezado Index.html:
También puede establecer pageTitle y pageDescription en valores dinámicos, como devolver datos de una llamada REST:
Una vez más, otros pueden tener mejores ideas sobre cómo abordar esto, pero como estoy usando una representación previa, mis necesidades se están cumpliendo.
fuente
Gracias a Tosh Shimayama por su solución.
Pensé que no era tan limpio poner un servicio directamente en él
$scope
, así que aquí está mi ligera variación al respecto: http://plnkr.co/edit/QJbuZZnZEDOBcYrJXWWsEl controlador (que en la respuesta original me pareció demasiado tonto) crea un objeto ActionBar, y este está incluido en $ scope.
El objeto es responsable de consultar realmente el servicio. También oculta del alcance $ la llamada para establecer la URL de la plantilla, que en su lugar está disponible para que otros controladores establezcan la URL.
fuente
El Sr. Hash tuvo la mejor respuesta hasta ahora, pero la solución a continuación lo hace ideal (para mí) al agregar los siguientes beneficios:
En el enrutador:
En el bloque de ejecución:
fuente
La solución mejor y dinámica que he encontrado es usar $ watch para rastrear los cambios de las variables y luego actualizar el título.
fuente