Existe-t-il un moyen de retrouver l'état précédent de l'état actuel?
Par exemple, j'aimerais savoir quel était l'état précédent avant l'état actuel B (où l'état précédent aurait été l'état A).
Je ne parviens pas à le trouver dans les pages doc de github ui-router.
ui-router ne suit pas l'état précédent une fois la transition effectuée, mais l'événement $stateChangeSuccess
est diffusé sur le $rootScope
lorsque l'état change.
Vous devriez pouvoir saisir l'état antérieur de cet événement (from
est l'état que vous quittez):
$rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
//assign the "from" parameter to something
});
J'utilise resol pour enregistrer les données d'état actuelles avant de passer au nouvel état:
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;
}]
}
});
}]);
Par souci de lisibilité, je vais placer ici ma solution (basée sur l'anwser de stu.salsbury).
Ajoutez ce code au modèle de résumé de votre application pour qu'il soit exécuté sur toutes les pages.
$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)
});
Assure le suivi des modifications dans rootScope. C'est très pratique.
Dans l'exemple suivant, j'ai créé un decorator
(une seule exécution par application lors de la phase de configuration) et ajouté une propriété supplémentaire au service $state
, de sorte que cette approche n'ajoute pas . variables globales à $rootscope
et n’a pas besoin d’ajouter de dépendance à d’autres services que $state
.
Dans mon exemple, je devais rediriger un utilisateur vers la page d'index alors qu'il était déjà connecté et qu'il ne devait pas le rediriger vers la page "protégée" précédente après la connexion.
Les seuls services inconnus (pour vous) que j'utilise sont authenticationFactory
et appSettings
:
authenticationFactory
n'administre que l'identifiant de l'utilisateur. Dans ce cas, j'utilise uniquement une méthode pour identifier si l'utilisateur est connecté ou non.appSettings
sont des constantes juste pour ne pas utiliser des chaînes partout. appSettings.states.login
et appSettings.states.register
contiennent le nom de l'état pour l'URL de connexion et d'enregistrement.Ensuite, dans n'importe quel controller
/service
etc, vous devez injecter le service $state
et vous pouvez accéder aux URL actuelles et précédentes comme ceci:
$state.current.name
$state.previous.route.name
Depuis la console Chrome:
var injector = angular.element(document.body).injector();
var $state = injector.get("$state");
$state.current.name;
$state.previous.route.name;
mise en œuvre:
(J'utilise angular-ui-router v0.2.17
et 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);
Ajouter une nouvelle propriété appelée {previous} à $ state sur $ 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;
...
}
Maintenant, partout où vous en avez besoin, vous pouvez utiliser $ state.
previous:Object
name:"route name"
params:Object
someParam:"someValue"
resolve:Object
template:"route template"
url:"/route path/:someParam"
Et utilisez-le comme ceci:
$state.go( $state.previous.name, $state.previous.params );
Je suis coincé avec le même problème et trouve le moyen le plus simple de le faire ...
//Html
<button type="button" onclick="history.back()">Back</button>
OR
//Html
<button type="button" ng-click="goBack()">Back</button>
//JS
$scope.goBack = function() {
window.history.back();
};
(Si vous voulez que ce soit plus testable, injectez le service $ window dans votre contrôleur et utilisez $ window.history.back ()).
J'utilise une approche similaire à celle de Endy Tjahjono.
Ce que je fais est de sauvegarder la valeur de l'état actuel avant de faire une transition. Permet de voir sur un exemple; imaginez cela dans une fonction exécutée lorsque vous cliquez sur ce qui déclenche la transition:
$state.go( 'state-whatever', { previousState : { name : $state.current.name } }, {} );
La clé ici est l’objet params (une carte des paramètres qui seront envoyés à l’état) -> { previousState : { name : $state.current.name } }
Note: notez que je ne fais que "sauvegarder" l'attribut name de l'objet $ state, car c'est la seule chose dont j'ai besoin pour sauvegarder l'état. Mais nous pourrions avoir l'objet d'état entier.
Ensuite, déclarez "tout ce que" a été défini comme ceci:
.state( 'user-edit', {
url : 'whatever'
templateUrl : 'whatever',
controller: 'whateverController as whateverController',
params : {
previousState: null,
}
});
Ici, le point clé est l’objet params.
params : {
previousState: null,
}
Ensuite, dans cet état, nous pouvons obtenir l'état précédent comme ceci:
$state.params.previousState.name
Voici une solution vraiment élégante de Chris Thielen i-router-extras: $ previousState
var previous = $previousState.get(); //Gets a reference to the previous state.
previous
est un objet qui ressemble à: { state: fromState, params: fromParams }
où FromState est l'état précédent et fromParams, les paramètres d'état précédents.
Ok, je sais que je suis en retard à la fête ici, mais je suis nouveau à angular. J'essaie de faire en sorte que cela rentre dans le guide de rédaction de John Papa ici. Je voulais faire cela réutilisable alors j'ai créé dans un bloc. Voici ce que je suis venu avec:
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;
});
}
}
})();
core.module
(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
}
})();
Toute critique sur ce code ne pourra que m'aider, alors laissez-moi savoir où je peux améliorer ce code.
Si vous avez juste besoin de cette fonctionnalité et souhaitez l'utiliser dans plusieurs contrôleurs, il s'agit d'un service simple pour suivre l'historique des itinéraires:
(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;
}
})();
où le "noyau" dans .module ("noyau") serait le nom de votre application/module. Exiger le service en tant que dépendance de votre contrôleur, puis dans votre contrôleur, vous pouvez faire: $scope.routeHistory = RouterTracker.getRouteHistory()
Je garde une trace des états précédents dans $ rootScope, donc chaque fois que j'en aurai besoin, j'appellerai simplement la ligne de code ci-dessous.
$state.go($rootScope.previousState);
Dans App.js:
$rootScope.$on('$stateChangeSuccess', function(event, to, toParams, from, fromParams) {
$rootScope.previousState = from.name;
});
Pour UI-Router (> = 1.0), les événements StateChange sont obsolètes. Pour un guide de migration complet, cliquez ici
Pour obtenir l'état précédent de l'état actuel dans UI-Router 1.0+:
app.run(function ($transitions) {
$transitions.onSuccess({}, function (trans) {
// previous state and paramaters
var previousState = trans.from().name;
var previousStateParameters = trans.params('from');
});
});