it-swarm.com.de

Angular - UI-Router erhalten vorherigen Status

Gibt es eine Möglichkeit, den vorherigen Status des aktuellen Status abzurufen?

Zum Beispiel möchte ich wissen, was der vorherige Zustand vor dem aktuellen Zustand B war (wo der vorherige Zustand A gewesen wäre).

Ich bin nicht in der Lage, es in Ui-Router Github Doc-Seiten zu finden.

148
Mihai H

ui-router verfolgt nach dem Übergang nicht den vorherigen Status, sondern das Ereignis $stateChangeSuccess wird ausgestrahlt auf dem $rootScope wenn sich der Zustand ändert.

Sie sollten in der Lage sein, den vorherigen Status von diesem Ereignis abzurufen (from ist der Status, den Sie verlassen):

$rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
   //assign the "from" parameter to something
});
130
laurelnaiad

Ich speichere die Daten des aktuellen Status mit der Funktion "Entschlossen", bevor ich in den neuen Status wechsle:

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;
                }]
            }
        });
}]);
142
Endy Tjahjono

Aus Gründen der Lesbarkeit werde ich meine Lösung (basierend auf der Antwort von stu.salsbury) hier platzieren.

Fügen Sie diesen Code zur abstrakten Vorlage Ihrer App hinzu, damit er auf jeder Seite ausgeführt wird.

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

Verfolgt die Änderungen in rootScope. Es ist ziemlich praktisch.

98
Federico

Im folgenden Beispiel habe ich ein decorator erstellt (wird in der Konfigurationsphase nur einmal pro App ausgeführt) und dem Dienst $state Eine zusätzliche Eigenschaft hinzugefügt, sodass bei diesem Ansatz kein global Variablen zu $rootscope und muss keine zusätzliche Abhängigkeit zu anderen Diensten als $state hinzufügen.

In meinem Beispiel musste ich einen Benutzer zur Indexseite umleiten, als er bereits angemeldet war und als er ihn nach der Anmeldung nicht zur vorherigen "geschützten" Seite umleiten sollte.

Die einzigen unbekannten Dienste (für Sie), die ich benutze, sind authenticationFactory und appSettings:

  • authenticationFactory verwaltet nur die Benutzeranmeldung. In diesem Fall benutze ich nur eine Methode, um festzustellen, ob der Benutzer angemeldet ist oder nicht.
  • appSettings sind Konstanten, um Zeichenfolgen nicht überall zu verwenden. appSettings.states.login Und appSettings.states.register Enthalten den Namen des Status für die Anmelde- und Registrierungs-URL.

Dann müssen Sie in jedem controller/service usw. den Dienst $state Einfügen und können auf die aktuelle und vorherige URL wie folgt zugreifen:

  • Aktuell: $state.current.name
  • Zurück: $state.previous.route.name

Über die Chrome Konsole:

var injector = angular.element(document.body).injector();
var $state = injector.get("$state");
$state.current.name;
$state.previous.route.name;

Implementierung:

(Ich verwende angular-ui-router v0.2.17 Und 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);
14
CodeArtist

Fügen Sie $ state in $ stateChangeStart eine neue Eigenschaft mit dem Namen {previous} hinzu

$rootScope.$on( '$stateChangeStart', ( event, to, toParams, from, fromParams ) => {
    // Add {fromParams} to {from}
    from.params = fromParams;

    // Assign {from} to {previous} in $state
    $state.previous = from;
    ...
}

Jetzt können Sie überall dort, wo Sie $ state benötigen, die vorherige Version verwenden

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

Und benutze es so:

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

Ich habe das gleiche Problem und finde den einfachsten Weg, dies zu tun ...

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

(Wenn Sie mehr Testmöglichkeiten wünschen, fügen Sie den $ window-Dienst in Ihren Controller ein und verwenden Sie $ window.history.back ()).

9
ProCylon

Ich benutze einen ähnlichen Ansatz wie Endy Tjahjono.

Ich speichere den Wert des aktuellen Status, bevor ich einen Übergang vornehme. Sehen wir uns ein Beispiel an. Stellen Sie sich dies in einer Funktion vor, die ausgeführt wird, wenn Sie auf das klicken, was den Übergang auslöst:

$state.go( 'state-whatever', { previousState : { name : $state.current.name } }, {} );

Der Schlüssel hier ist das params-Objekt (eine Karte der Parameter, die an den Zustand gesendet werden) -> { previousState : { name : $state.current.name } }

Hinweis: Beachten Sie, dass ich nur das Namensattribut des $ state-Objekts "speichere", da dies das einzige ist, was ich zum Speichern des Status benötige. Aber wir könnten das ganze Staatsobjekt haben.

Dann geben Sie an, was auch immer wie folgt definiert wurde:

.state( 'user-edit', {
  url : 'whatever'
  templateUrl : 'whatever',
  controller: 'whateverController as whateverController',
  params : {
    previousState: null,
  }
});

Der entscheidende Punkt ist hier das Objekt params.

params : {
  previousState: null,
}

In diesem Zustand können wir dann den vorherigen Zustand wie folgt erhalten:

$state.params.previousState.name
8
avcajaraville

Hier ist eine wirklich elegante Lösung von Chris Thielen I-Router-Extras: $ previousState

var previous = $previousState.get(); //Gets a reference to the previous state.

previous ist ein Objekt, das wie folgt aussieht: { state: fromState, params: fromParams } wobei fromState der vorherige Status und fromParams der vorherige Statusparameter ist.

6
Ephraim

Ok, ich weiß, dass ich zu spät zur Party hier bin, aber ich bin neu in eckigen. Ich versuche, dies in den John Papa Style Guide hier einzufügen. Ich wollte das wiederverwendbar machen, also habe ich es in einem Block erstellt. Folgendes habe ich mir ausgedacht:

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

Jede Kritik an diesem Code hilft mir nur. Lassen Sie mich wissen, wo ich diesen Code verbessern kann.

4
fizch

Wenn Sie diese Funktionalität nur benötigen und sie in mehr als einem Controller verwenden möchten, ist dies ein einfacher Dienst zum Verfolgen des Routenverlaufs:

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

wobei der "Core" in .module ("Core") der Name Ihrer App/Ihres Moduls ist. Benötigen Sie den Dienst als Abhängigkeit von Ihrem Controller, dann können Sie in Ihrem Controller Folgendes tun: $scope.routeHistory = RouterTracker.getRouteHistory()

2
user1970565

Ich behalte die vorherigen Zustände in $ rootScope im Auge, daher rufe ich bei Bedarf einfach die folgende Codezeile auf.

$state.go($rootScope.previousState);

In App.js:

$rootScope.$on('$stateChangeSuccess', function(event, to, toParams, from, fromParams) {
  $rootScope.previousState = from.name;
});
1
Naveen Kumar V

Für UI-Router (> = 1.0) sind StateChange-Ereignisse veraltet. Für eine vollständige Migrationsanleitung klicken Sie auf hier

So rufen Sie den vorherigen Status des aktuellen Status in UI-Router 1.0+ ab:

app.run(function ($transitions) {
    $transitions.onSuccess({}, function (trans) {
         // previous state and paramaters
         var previousState = trans.from().name;
         var previousStateParameters = trans.params('from');
    });
});
0
NagarajuRaghava