angularjs - sref - Angular-ui-enrutador obtener estado anterior
ui sref angularjs example (13)
¿Hay alguna manera de obtener el estado previo del estado actual?
Por ejemplo, me gustaría saber cuál era el estado anterior antes del estado actual B (donde el estado anterior habría sido el estado A).
No puedo encontrarlo en las páginas de doc. Ui-enrutador github.
Agregue una nueva propiedad llamada {previous} a $ state en $ stateChangeStart
$rootScope.$on( ''$stateChangeStart'', ( event, to, toParams, from, fromParams ) => {
// Add {fromParams} to {from}
from.params = fromParams;
// Assign {from} to {previous} in $state
$state.previous = from;
...
}
Ahora, en cualquier lugar que necesite puede usar $ state, tendrá disponible previamente
previous:Object
name:"route name"
params:Object
someParam:"someValue"
resolve:Object
template:"route template"
url:"/route path/:someParam"
Y úsalo así:
$state.go( $state.previous.name, $state.previous.params );
Aquí hay una solución realmente elegante de Chris Thielen ui-router-extras: $ previousState
var previous = $previousState.get(); //Gets a reference to the previous state.
previous
es un objeto que se ve así: { state: fromState, params: fromParams }
donde fromState es el estado anterior y fromParams es los parámetros de estado previos.
En aras de la legibilidad, ubicaré aquí mi solución (basada en el artículo de stu.salsbury''s).
Agregue este código a la plantilla de resumen de su aplicación para que se ejecute en todas las páginas.
$rootScope.previousState;
$rootScope.currentState;
$rootScope.$on(''$stateChangeSuccess'', function(ev, to, toParams, from, fromParams) {
$rootScope.previousState = from.name;
$rootScope.currentState = to.name;
console.log(''Previous state:''+$rootScope.previousState)
console.log(''Current state:''+$rootScope.currentState)
});
Realiza un seguimiento de los cambios en rootScope. Es bastante práctico.
En el siguiente ejemplo, creé un decorator
(se ejecuta solo una vez por aplicación en la fase de configuración) y agrego una propiedad adicional al servicio $state
, por lo que este enfoque no agrega variables globales a $rootscope
y no requiere agregar ninguna dependencia adicional a otro servicios que $state
.
En mi ejemplo, necesitaba redirigir a un usuario a la página de índice cuando ya había iniciado sesión y cuando no debía redirigirlo a la página "protegida" previa después de iniciar sesión.
Los únicos servicios desconocidos (para usted) que uso son authenticationFactory
y appSettings
:
-
authenticationFactory
simplemente administra el inicio de sesión del usuario. En este caso, utilizo solo un método para identificar si el usuario está conectado o no. -
appSettings
son constantes solo para no utilizar cadenas en todas partes.appSettings.states.login
yappSettings.states.register
contienen el nombre del estado para el inicio de sesión y la URL de registro.
Luego, en cualquier controller
/ service
etc. necesita inyectar $state
service y puede acceder a la url actual y anterior de esta manera:
- Actual:
$state.current.name
- Anterior:
$state.previous.route.name
Desde la consola de Chrome:
var injector = angular.element(document.body).injector();
var $state = injector.get("$state");
$state.current.name;
$state.previous.route.name;
Implementación:
(Estoy usando angular-ui-router v0.2.17
y angularjs v1.4.9
)
(function(angular) {
"use strict";
function $stateDecorator($delegate, $injector, $rootScope, appSettings) {
function decorated$State() {
var $state = $delegate;
$state.previous = undefined;
$rootScope.$on("$stateChangeSuccess", function (ev, to, toParams, from, fromParams) {
$state.previous = { route: from, routeParams: fromParams }
});
$rootScope.$on("$stateChangeStart", function (event, toState/*, toParams, fromState, fromParams*/) {
var authenticationFactory = $injector.get("authenticationFactory");
if ((toState.name === appSettings.states.login || toState.name === appSettings.states.register) && authenticationFactory.isUserLoggedIn()) {
event.preventDefault();
$state.go(appSettings.states.index);
}
});
return $state;
}
return decorated$State();
}
$stateDecorator.$inject = ["$delegate", "$injector", "$rootScope", "appSettings"];
angular
.module("app.core")
.decorator("$state", $stateDecorator);
})(angular);
Estoy atrapado con el mismo problema y encuentro la manera más fácil de hacer esto ...
//Html
<button type="button" onclick="history.back()">Back</button>
O
//Html
<button type="button" ng-click="goBack()">Back</button>
//JS
$scope.goBack = function() {
window.history.back();
};
(Si desea que sea más comprobable, inserte el servicio $ window en su controlador y use $ window.history.back ()).
Llevo un registro de los estados previos en $ rootScope , de modo que siempre que lo necesite me limitaré a llamar a la siguiente línea de código.
$state.go($rootScope.previousState);
En App.js :
$rootScope.$on(''$stateChangeSuccess'', function(event, to, toParams, from, fromParams) {
$rootScope.previousState = from.name;
});
Ok, sé que llego tarde a la fiesta aquí, pero soy nuevo en angular. Estoy tratando de hacer que esto encaje en la guía de estilo de John Papa aquí. Quería hacer esto reutilizable, así que creé en un bloque. Aquí es lo que se me ocurrió:
previousStateProvider
(function () {
''use strict'';
angular.module(''blocks.previousState'')
.provider(''previousState'', previousStateProvider);
previousStateProvider.$inject = [''$rootScopeProvider''];
function previousStateProvider($rootScopeProvider) {
this.$get = PreviousState;
PreviousState.$inject = [''$rootScope''];
/* @ngInject */
function PreviousState($rootScope) {
$rootScope.previousParms;
$rootScope.previousState;
$rootScope.currentState;
$rootScope.$on(''$stateChangeSuccess'', function (ev, to, toParams, from, fromParams) {
$rootScope.previousParms = fromParams;
$rootScope.previousState = from.name;
$rootScope.currentState = to.name;
});
}
}
})();
módulo principal
(function () {
''use strict'';
angular.module(''myApp.Core'', [
// Angular modules
''ngMessages'',
''ngResource'',
// Custom modules
''blocks.previousState'',
''blocks.router''
// 3rd Party Modules
]);
})();
core.config
(function () {
''use strict'';
var core = angular.module(''myApp.Core'');
core.run(appRun);
function appRun(previousState) {
// do nothing. just instantiating the state handler
}
})();
Cualquier crítica sobre este código solo me ayudará, así que avíseme por favor dónde puedo mejorar este código.
Puede devolver el estado de esta manera:
$state.go($state.$current.parent.self.name, $state.params);
Un ejemplo:
(function() {
''use strict''
angular.module(''app'')
.run(Run);
/* @ngInject */
function Run($rootScope, $state) {
$rootScope.back = function() {
$state.go($state.$current.parent.self.name, $state.params);
};
};
})();
Si solo necesita esta funcionalidad y desea usarla en más de un controlador, este es un servicio simple para rastrear el historial de rutas:
(function () {
''use strict'';
angular
.module(''core'')
.factory(''RouterTracker'', RouterTracker);
function RouterTracker($rootScope) {
var routeHistory = [];
var service = {
getRouteHistory: getRouteHistory
};
$rootScope.$on(''$stateChangeSuccess'', function (ev, to, toParams, from, fromParams) {
routeHistory.push({route: from, routeParams: fromParams});
});
function getRouteHistory() {
return routeHistory;
}
return service;
}
})();
donde el ''núcleo'' en .module (''core'') sería el nombre de su aplicación / módulo. Requiera el servicio como una dependencia de su controlador, luego en su controlador puede hacer: $scope.routeHistory = RouterTracker.getRouteHistory()
Una solución realmente simple es simplemente editar la cadena $ state.current.name y cortar todo incluyendo y después del último ''.'' - obtienes el nombre del estado principal. Esto no funciona si saltas mucho entre estados porque solo analiza la ruta actual. Pero si tus estados corresponden a donde realmente estás, entonces esto funciona.
var previousState = $state.current.name.substring(0, $state.current.name.lastIndexOf(''.''))
$state.go(previousState)
Utilizo resolve para guardar los datos de estado actuales antes de pasar al nuevo estado:
angular.module(''MyModule'')
.config([''$stateProvider'', function ($stateProvider) {
$stateProvider
.state(''mystate'', {
templateUrl: ''mytemplate.html'',
controller: ["PreviousState", function (PreviousState) {
if (PreviousState.Name == "mystate") {
// ...
}
}],
resolve: {
PreviousState: ["$state", function ($state) {
var currentStateData = {
Name: $state.current.name,
Params: $state.params,
URL: $state.href($state.current.name, $state.params)
};
return currentStateData;
}]
}
});
}]);
Utilizo un enfoque similar a lo que hace Endy Tjahjono.
Lo que hago es guardar el valor del estado actual antes de hacer una transición. Veamos un ejemplo; Imagínese esto dentro de una función ejecutada cuando cliquea a lo que desencadena la transición:
$state.go( ''state-whatever'', { previousState : { name : $state.current.name } }, {} );
La clave aquí es el objeto params (un mapa de los parámetros que se enviarán al estado) -> { previousState : { name : $state.current.name } }
Nota: tenga en cuenta que solo estoy "guardando" el atributo de nombre del objeto $ state, porque es lo único que necesito para guardar el estado. Pero podríamos tener todo el objeto del estado.
Luego, indique "lo que sea" se definió así:
.state( ''user-edit'', {
url : ''whatever''
templateUrl : ''whatever'',
controller: ''whateverController as whateverController'',
params : {
previousState: null,
}
});
Aquí, el punto clave es el objeto params.
params : {
previousState: null,
}
Entonces, dentro de ese estado, podemos obtener el estado anterior así:
$state.params.previousState.name
ui-router no rastrea el estado previo una vez que transiciones, pero el evento $stateChangeSuccess
se transmite en $rootScope
cuando el estado cambia.
Debería poder detectar el estado anterior de ese evento ( from
el estado en el que se está yendo):
$rootScope.$on(''$stateChangeSuccess'', function (ev, to, toParams, from, fromParams) {
//assign the "from" parameter to something
});