angularjs - template - Establecer el título de la página usando UI-Router
ui router angularjs template (14)
¿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:
<section
your-page-title="{{''somePage'' | translate}}">
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
<title ng-bind="$root.pageTitle"></title>
¿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.
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,
// <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>
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 dinámico basado en el estado actual. También funciona correctamente con el historial del navegador.
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:
<title data-ng-bind="$state.current.data.pageTitle + '' - Optional text''">Failsafe text</title>
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.''
},
})
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 .run 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, <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;
}])
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 ...
<title ng-bind="$state.current.data.pageTitle"></title>
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!
Me pareció muy fácil de esta manera :
.state(''app.staff.client'', {
url: ''/client/mine'',
title: ''My Clients''})
y luego en mi HTML así:
<h3>{{ $state.current.title }}</h3>
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);
}
}
}
])
Agregue los siguientes a su index.html:
<title page-title ng-bind="page_title"></title>
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;
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.
Tal vez puedas probar esta directiva.
https://github.com/afeiship/angular-dynamic-title
Aquí está el ejemplo:
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!'');
});
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;
});
});
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:
<title update-title></title>
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>{{title}}</title>
Demostración: http://run.plnkr.co/d4s3qBikieq8egX7/#/credits
$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 help 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 sintaxis 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: "<foo-widget layout=''row''/>",
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: "<bar-widget code=''{{code}}'' layout=''row''/>",
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 sintaxis 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.