157 votes

Angular - ui-router récupérer l'état précédent

Existe-t-il un moyen d'obtenir l'état précédent de l'état actuel ?

Par exemple, je voudrais 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 suis pas en mesure de le trouver dans les pages de doc ui-router github.

151voto

Endy Tjahjono Points 4458

J'utilise resolve pour sauvegarder les données de l'état actuel 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: angular.copy($state.params),
                        URL: $state.href($state.current.name, $state.params)
                    };
                    return currentStateData;
                }]
            }
        });
}]);

135voto

stu.salsbury Points 1417

L'ui-routeur ne suit pas l'état précédent une fois qu'il a effectué la transition, mais l'événement $stateChangeSuccess est diffusé sur le $rootScope lorsque l'état change.

Vous devriez être en mesure de récupérer 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
});

100voto

Federico Points 671

Pour des raisons de lisibilité, je vais placer ma solution (basée sur la réponse de Stu.Salsbury) ici.

Ajoutez ce code au modèle abstrait de votre application pour qu'il s'exécute sur chaque page.

$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)
});

Garde la trace des changements dans le rootScope. C'est assez pratique.

14voto

Jorge Code Points 659

Dans l'exemple suivant, j'ai créé un decorator (ne s'exécute qu'une fois par application lors de la phase de configuration) et ajoute une propriété supplémentaire à $state service, cette approche n'ajoute donc pas mondial variables à $rootscope et ne nécessite pas d'ajouter une dépendance supplémentaire à d'autres services que le $state .

Dans mon exemple, j'avais besoin de rediriger un utilisateur vers la page d'index lorsqu'il était déjà connecté et, dans le cas contraire, de 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 les suivants authenticationFactory y appSettings :

  • authenticationFactory ne fait qu'administrer la connexion de l'utilisateur. Dans ce cas, j'utilise seulement une méthode pour identifier si l'utilisateur est connecté ou non.
  • appSettings sont des constantes juste pour ne pas utiliser les chaînes de caractères partout. appSettings.states.login y appSettings.states.register contient le nom de l'état pour l'url de connexion et d'enregistrement.

Ensuite, dans tout controller / service etc vous devez injecter $state et vous pouvez accéder à l'url actuelle et précédente comme ceci :

  • Actuel : $state.current.name
  • Précédent : $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 <code>angular-ui-router v0.2.17</code> y <code>angularjs v1.4.9</code> )

(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);

12voto

Luis Points 31

Ajouter une nouvelle propriété appelée {précédent} à $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 avez besoin d'utiliser $state, vous aurez les précédents disponibles.

previous:Object
    name:"route name"
    params:Object
        someParam:"someValue"
    resolve:Object
    template:"route template"
    url:"/route path/:someParam"

Et utilisez-le comme ça :

$state.go( $state.previous.name, $state.previous.params );

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X