angularjs - example - ui-router params
¿Cómo accedo a la propiedad ''resolver'' de un estado raíz de UI-Router desde $ stateChangeStart? (5)
Estoy tratando de implementar un sistema de verificación de acceso de usuarios y verificación de acceso en mi aplicación, sin embargo, sigo golpeando obstáculos. Creo que lo tengo de la manera correcta esta vez, pero tengo un último obstáculo.
Un poco de historia: intenté poner todo el código en $ rootScope.on ($ startChangeStart) y funcionó, horriblemente ... pero funcionó. La ruta siempre fue redirigida, pero debido a la verificación de autenticación en el backend, se mostró la primera página de solicitud por 1/2 un segundo y luego la página de redireccionamiento cada vez. Por lo tanto, intenté "pausar" la carga de la página llamando a evt.preventDefault () justo al inicio de la función $ startChangeStart, que funcionó, pero al intentar volver al usuario a la ruta original, causó un bucle infinito en el enrutador.
Entonces, después de investigar más y leer muchas publicaciones en la pila, estoy seguro de que ''resolver:'' es el lugar adecuado para poner la comprobación de autenticación para garantizar que la página no se carga mientras ocurre, y luego redirigir al usuario si es necesario desde $ startChangeStart. ($ estado y evento siempre están indefinidos en mis intentos de inyectarlos en una función de resolución) Parece la combinación ganadora.
Mi problema: tengo la resolución sobre el estado raíz en mi aplicación: ''main''
Esto fue para evitar la redundancia de código, sin embargo, no puedo determinar cómo acceder a las propiedades del estado raíz y, por lo tanto, el resultado de la resolución, desde la función $ stateChangeStart. El estado toState es el estado secundario, mientras que el estado fromState es el estado anterior o un estado abstracto con la ruta ''^'' ...
¿Tengo que poner la resolución en cada estado secundario para que esto funcione, o hay una manera de acceder al estado raíz desde este punto?
Configuración básica de la aplicación:
angular.module(''App'', [''ui.router'', ''ui.bootstrap'', ''ui.event'', ''AngularGM'', ''ngResource''])
.config([''$urlRouterProvider'', ''$stateProvider'', function($urlRouterProvider, $stateProvider){
$urlRouterProvider
.when(''/home'', ''/'')
.when('''', ''/'')
.when(''/sign-up/joe'', ''/sign-up'')
.otherwise(''/'');
$stateProvider
.state(''main'', {
url: '''',
abstract: true,
templateUrl: ''views/main.html'',
controller: ''MainCtrl'',
resolve: {
checkAccess: [''accountService'', function(accountService) {
accountService.checkAuth(function(){
accountService.checkAccess(function (access){
return access;
});
});
}]
}
})
.state(''main.home'', {
url: '''',
abstract: true,
templateUrl: ''views/home.html'',
controller: ''HomeCtrl''
})
.state(''main.home.index'', {
url: ''/'',
templateUrl: ''views/home/index.html''
});
.run([''$rootScope'', ''$state'', ''$stateParams'', ''accountService'', function ($rootScope, $state, $stateParams) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$rootScope.$on(''$stateChangeStart'', function(event, toState, toParams, fromState, fromParams) {
console.dir(toState);
console.dir(toParams);
console.dir(fromState);
console.dir(fromParams);
if (!toState.checkAccess.allowed) {
event.preventDefault();
$state.transitionTo(toState.checkAccess.newState);
}
});
}]);
Esta es la salida de las llamadas de console.dir () en los dos objetos de estado:
Object
name: "main.home.index"
templateUrl: "views/home/index.html"
url: "/"
__proto__: Object
Object
controller: "PlacesCtrl"
name: "main.places.search"
templateUrl: "views/places.html"
url: "/places"
__proto__: Object
Actualizar
Vaya, olvidé mencionar que la versión de AngularJS es v1.2.0-rc.2
$ state.current console.dir ()
Object
abstract: true
name: ""
url: "^"
views: null
__proto__: Object
¿Es posible hacer la redirección desde su servicio de cuenta? Si detecta que el usuario falla en sus funciones checkAuth o checkAccess, podría evitar que la devolución de llamada se ejecute y redirigir al usuario a su página de error (o inicio de sesión).
Otra cosa a considerar es implementar algún tipo de variable / cola de estados si desea redirigir a alguien a la página de inicio de sesión para actualizar su autorización / autenticación y luego volver al estado anterior.
Esta respuesta es muy tarde pero puede ser útil.
Las resoluciones de un estado y el evento $stateChangeStart
se ejecutan al mismo tiempo. Cuando intente acceder a los datos resueltos en $stateChangeStart
, no estará disponible, pero estará disponible cuando se $stateChangeSuccess
evento $stateChangeSuccess
.
Si usa $stateChangeStart
entonces deberá hacer checkAuth
desde el evento $stateChangeStart
de dos lugares y la resolución principal. Como tienen una ejecución paralela, se enviarán al servidor al menos 2 solicitudes de red para los mismos datos.
En su lugar, use $stateChangeSuccess
. El uso de esto asegurará que sus resoluciones se resuelvan y luego podrá verificar el acceso. Además, en lugar de acceder a las propiedades resueltas, acceda a los datos resueltos utilizando el servicio angular.
No necesitas usar la resolve
. Echa un vistazo a mi solución:
app.run ($rootScope, $state, Auth, ngDialog) ->
$rootScope.$on ''$stateChangeStart'', (e, to) ->
if to.authRequired and not Auth.isAuthenticated()
e.preventDefault()
Auth.currentUser().then(
(user) ->
$state.go(to)
(failure) ->
$rootScope.storedState = to
$state.go(''main'')
ngDialog.closeAll()
ngDialog.open
template: ''modals/login.html''
controller: ''loginCtrl''
className: ''ngdialog-theme-default''
)
Utilizo angular_devise y ngDialog pero son opcionales y puedes implementarlo con el servicio de tu propio usuario.
Sí, creo que puedes acceder al estado raíz desde la función $stateChangeStart
.
Cuando utilizo AngularJS puro, normalmente uso current.$$route
Por ejemplo, utilizando la siguiente ruta.
.when(''/home'', {
title:''Home'',
bodyClass: ''meetings'',
controler: ''HomeCtrl''
})
Puedo acceder al estado raíz como tal
$rootScope.$on(''$routeChangeSuccess'', function (event, current, previous) {
if (current.$$route) {
$rootScope.title = current.$$route.title;
$rootScope.bodyClass = current.$$route.bodyClass;
}
});
Usar ui-router
es un poco diferente, ya que se llama $state.current
. Y puede acceder a todas las propiedades asociadas a cualquier ruta que toque (por ejemplo: $ state.current.url)
Así que en tu código podrías tener algo como esto
.run([''$rootScope'', ''$state'', ''$stateParams'', function ($rootScope, $state, $stateParams) {
$rootScope.$on(''$stateChangeStart'', function(event, toState, toParams, fromState, fromParams) {
console.log($state.current.url);
});
}]);
Si inicializa su estado con un objeto vacío predeterminado en la resolución, podrá manipularlo dentro de $stateChangeStart
.
$stateProvider
.state ''home'',
url: "/"
resolve: {}
...
$rootScope.$on ''$stateChangeStart'', (e, toState, toParams, fromState, fromParams) ->
toState.resolve.x = ->
$timeout ->
alert "done"
, 3000
Consulte https://github.com/angular-ui/ui-router/issues/1165