angularjs - sref - Resolución de estado anidado enrutador de UI angular en estados secundarios
ui-router angular 6 (2)
En una aplicación angular en la que estoy trabajando, me gustaría que hubiera un estado padre abstracto que debe resolver ciertas dependencias para todos los estados de sus hijos. Específicamente, me gustaría que todos los estados exijan que un usuario autenticado herede esa dependencia de algún estado authroot.
Me estoy encontrando con problemas que tienen la dependencia de los padres no siempre se vuelve a resolver. Idealmente, me gustaría que el estado padre verifique que el usuario todavía esté conectado para cualquier estado secundario automáticamente. En los docs , dice
Los estados secundarios heredarán las dependencias resueltas de los estados principales, que pueden sobrescribir.
Estoy descubriendo que la dependencia de los padres solo se vuelve a resolver si ingreso un estado secundario desde un estado fuera del padre, pero no si se mueve entre estados hermanos.
En este ejemplo, si se mueve entre los estados authroot.testA y authroot.testB, el método GetUser solo se llama una vez. Cuando te mueves al other
estado y vuelves, se ejecutará nuevamente.
Puedo poner la dependencia del usuario en cada uno de los estados secundarios para asegurar que se llame al método cada vez que ingrese cualquiera de esos estados, pero eso parece frustrar el propósito de la dependencia heredada.
¿Estoy entendiendo los documentos incorrectamente? ¿Hay alguna manera de forzar al estado padre a volver a resolver sus dependencias incluso cuando el estado cambia entre hermanos?
<!doctype html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.0/angular-ui-router.min.js"></script>
<script>
(function(ng) {
var app = ng.module("Test", ["ui.router"]);
app.config(["$stateProvider", "$urlRouterProvider", function(sp, urp) {
urp.otherwise("/testA");
sp.state("authroot", {
abstract: true,
url: "",
template: "<div ui-view></div>",
resolve: {User: ["UserService", function(UserService) {
console.log("Resolving dependency...");
return UserService.GetUser();
}]}
});
sp.state("authroot.testA", {
url: "/testA",
template: "<h1>Test A {{User|json}}</h1>",
controller: "TestCtrl"
});
sp.state("authroot.testB", {
url: "/testB",
template: "<h1>Test B {{User|json}}</h1>",
controller: "TestCtrl"
});
sp.state("other", {
url: "/other",
template: "<h1>Other</h1>",
});
}]);
app.controller("TestCtrl", ["$scope", "User", function($scope, User) {$scope.User = User;}]);
app.factory("UserService", ["$q", "$timeout", function($q, $timeout) {
function GetUser() {
console.log("Getting User information from server...");
var d = $q.defer();
$timeout(function(){
console.log("Got User info.");
d.resolve({UserName:"JohnDoe1", OtherData: "asdf"});
}, 500);
return d.promise;
};
return {
GetUser: GetUser
};
}]);
})(window.angular);
</script>
</head>
<body ng-app="Test">
<a ui-sref="authroot.testA">Goto A</a>
<a ui-sref="authroot.testB">Goto B</a>
<a ui-sref="other">Goto Other</a>
<div ui-view>Loading...</div>
</body>
</html>
La forma en que considero que el router de red es excepcional, está en el comportamiento que acaba de describir.
Pensemos en alguna entidad, por ejemplo, Contacto. Entonces sería bueno tener un lado derecho que nos muestre la lista de Contactos, la parte izquierda el detalle. Por favor, consulte los conceptos básicos sobre el uso de ui-router con AngularJS para una rápida revisión del diseño. Una cita
ui-router abarca por completo la naturaleza de máquina de estado de un sistema de enrutamiento. Le permite definir estados y hacer la transición de su aplicación a esos estados. La verdadera victoria es que te permite desacoplar estados anidados y hacer diseños muy complicados de una manera elegante.
Debe pensar en su ruta de una manera un poco diferente, pero una vez que entienda el enfoque basado en el estado, creo que le gustará.
Ok, ¿por qué todo eso?
Porque podemos tener un Contact
estatal que represente una lista. Diga una lista fija desde la perspectiva del detalle . (Omita el filtro de paginación de búsqueda ahora) Podemos hacer clic en la lista y Contact.Detail(ID)
a un estado Contact.Detail(ID)
, para ver solo el elemento seleccionado. Y luego selecciona otro contacto / artículo.
Aquí la ventaja de los estados anidados viene:
La lista (el
Contact
estado) no se vuelve a cargar. Mientras que el estado hijoContact.Detail
es.
Eso debería explicar por qué el comportamiento "extraño" debe tratarse como correcto.
Para responder a su pregunta, cómo manejar el estado del usuario. Usaría algún hermano muy superior de un estado de ruta, con su vista y controlador separados y algún ciclo de vida ... activado en algunos ciclos
La respuesta corta real es uso:
$rootScope.$on("$stateChangeStart")
para escuchar cualquier cambio de alcance y hacer las acciones apropiadas.
Una respuesta más larga es, revisa el violín: http://jsfiddle.net/jasallen/SZGjN/1/
Tenga en cuenta que he usado app.run, lo que significa que estoy resolviendo al usuario por cada cambio de estado. Si desea limitarlo a los cambios de estado mientras authRoot está en la paternidad, coloque la $stateChangeStart
en el controlador authRoot.