Angolare – l’interfaccia utente ha lo stato precedente

C’è un modo per ottenere lo stato precedente dello stato corrente?

Per esempio vorrei sapere quale era lo stato precedente prima dello stato attuale B (dove lo stato precedente sarebbe stato stato A).

Non riesco a trovarlo nelle pagine del github del documento ui-router.

ui-router non traccia lo stato precedente una volta transizioni, ma l’evento $stateChangeSuccess viene trasmesso su $rootScope quando lo stato cambia.

Dovresti essere in grado di catturare lo stato precedente da quell’evento ( from quello che stai lasciando):

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

Uso risoluzione per salvare i dati dello stato corrente prima di passare al nuovo stato:

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

Per motivi di leggibilità, inserirò qui la mia soluzione (basata sulla ricerca di stu.salsbury).

Aggiungi questo codice al modello astratto della tua app in modo che venga eseguito su ogni pagina.

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

Tiene traccia delle modifiche in rootScope. È abbastanza utile.

Nell’esempio seguente ho creato un decorator (viene eseguito una sola volta per app in fase di configurazione) e aggiunge una proprietà aggiuntiva al servizio $state , quindi questo approccio non aggiunge variabili globali a $rootscope e non richiede di aggiungere alcuna dipendenza aggiuntiva ad altri servizi di $state .

Nel mio esempio avevo bisogno di redirect un utente alla pagina dell’indice quando era già registrato e quando non lo aveva reindirizzato alla precedente pagina “protetta” dopo l’accesso.

Gli unici servizi sconosciuti (per te) che utilizzo sono authenticationFactory e appSettings :

  • authenticationFactory gestisce solo il login dell’utente. In questo caso, utilizzo solo un metodo per identificare se l’utente è connesso o meno.
  • appSettings sono costanti solo per non utilizzare le stringhe ovunque. appSettings.states.login e appSettings.states.register contengono il nome dello stato per l’accesso e l’url di registrazione.

Quindi in qualsiasi controller / service ecc. È necessario iniettare il servizio $state e puoi accedere all’url corrente e precedente come questo:

  • Corrente: $state.current.name
  • Precedente: $state.previous.route.name

Dalla console di Chrome:

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

Implementazione:

(Sto usando angular-ui-router v0.2.17 e 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); 

Aggiungi una nuova proprietà chiamata {precedente} a $ stato su $ 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; ... } 

Ora ovunque tu abbia bisogno puoi usare $ stato che avrai disponibile in precedenza

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

E usalo così:

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

Uso un approccio simile a quello che fa Endy Tjahjono.

Quello che faccio è di salvare il valore dello stato corrente prima di effettuare una transizione. Vediamo un esempio; immagina questo all’interno di una funzione eseguita quando cliking a qualsiasi cosa innesca la transizione:

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

La chiave qui è l’object params (una mappa dei parametri che verranno inviati allo stato) -> { previousState : { name : $state.current.name } }

Nota: si noti che Im “salva” solo l’attributo name dell’object $ state, perché è l’unica cosa di cui ho bisogno per salvare lo stato. Ma potremmo avere l’intero object di stato.

Quindi, lo stato “qualunque” è stato definito in questo modo:

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

Qui, il punto chiave è l’object params.

 params : { previousState: null, } 

Quindi, all’interno di quello stato, possiamo ottenere lo stato precedente in questo modo:

 $state.params.previousState.name 

Sono bloccato con lo stesso problema e trovare il modo più semplice per farlo …

 //Html  

O

 //Html  //JS $scope.goBack = function() { window.history.back(); }; 

(Se vuoi che sia più testabile, inserisci il servizio $ window nel tuo controller e usa $ window.history.back ()).

Ecco una soluzione davvero elegante di Chris Thielen ui-router-extras: $ previousState

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

previous è un object che assomiglia a: { state: fromState, params: fromParams } dove fromState è lo stato precedente e fromParams è i precedenti parametri di stato.

Ok, so che sono in ritardo per la festa qui, ma sono nuovo di spigoloso. Sto provando a farlo rientrare nella guida in stile John Papa qui. Volevo rendere questo riutilizzabile, così l’ho creato in un blocco. Ecco cosa mi è venuto in mente:

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

Qualsiasi critica su questo codice mi aiuterà solo, quindi per favore fatemi sapere dove posso migliorare questo codice.

Se hai solo bisogno di questa funzionalità e vuoi usarla in più di un controller, questo è un servizio semplice per tracciare la cronologia del percorso:

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

dove il ‘core’ in .module (‘core’) sarebbe il nome della tua app / modulo. Richiedere il servizio come dipendenza dal controller, quindi nel controller è ansible eseguire: $scope.routeHistory = RouterTracker.getRouteHistory()

Una soluzione davvero semplice è solo per modificare la stringa $ state.current.name e tagliare tutto compreso e dopo l’ultimo ‘.’ – ottieni il nome dello stato genitore. Questo non funziona se si salta molto tra stati perché solo analizza il percorso corrente. Ma se i tuoi stati corrispondono a quelli in cui sei effettivamente, allora funziona.

 var previousState = $state.current.name.substring(0, $state.current.name.lastIndexOf('.')) $state.go(previousState) 

Tengo traccia degli stati precedenti in $ rootScope , quindi ogni volta che ho bisogno chiamerò semplicemente la riga di codice sottostante.

 $state.go($rootScope.previousState); 

In App.js :

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

Puoi restituire lo stato in questo modo:

 $state.go($state.$current.parent.self.name, $state.params); 

Un esempio:

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