Açısal - ui-yönlendirici önceki durumu al


152

Mevcut durumun önceki durumunu almanın bir yolu var mı?

Örneğin, mevcut durum B'den önceki önceki durumun ne olduğunu bilmek istiyorum (önceki durum A durumu olurdu).

Ui-yönlendirici github doc sayfalarında bulamıyorum.


aşağıdaki cevap doğrudur, eğer dokümanlar yeterli yardım sağlamazsa
David Chase

Yanıtlar:


134

ui-router geçiş yaptıktan sonra önceki durumu izlemez, ancak durum değiştiğinde olay $stateChangeSuccessyayınlanır $rootScope.

Bu etkinlikten önceki durumu yakalayabilmeniz gerekir ( fromayrıldığınız durumdur):

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

3
"Gönderen" kullanan bir örnek ne olabilir?
Paul

Burada 'to' ve 'from', 'toState' ve 'fromState' anlamına gelir. Önceki URL'nizin localhost olduğunu düşünün: xxxx / çalışan ve denetleyici 'EmployeesController' olduğunda 'fromState' için örnek şudur: Object {url: "/ çalışanları", templateUrl: "/ çalışanları", denetleyici: "EmployeesController", adı: " çalışanları "}
Ranadheer Reddy

3
Bunu özetimde yaptım: `$ $ rootScope.previousState; $ rootScope.currentState; $ rootScope. $ on ('$ stateChangeSuccess', işlev (ev, to, toParams, fromParams) {$ rootScope.previousState = from.name; $ rootScope.currentState = to.name; console.log ('Önceki durum: '+ $ rootScope.previousState) console.log (' Şu anki durum: '+ $ rootScope.currentState)}); `RootScope'ta önceki ve güncel olanları takip eder. Oldukça kullanışlı!
Federico

@ Endy-tjahjono ( stackoverflow.com/a/25945003/2837519 ) çözümünü kullanmak , ui-router 1.x ürününün satır içi işlemidir .
Peter Ahlers

History.back () ile basit bir yolu seviyorum <a href="javascript:history.back()" class="btn btn-default no-radius">
Serip88

146

Yeni duruma geçmeden önce geçerli durum verilerini kaydetmek için çözümü kullanıyorum:

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

8
çok daha iyi başa daha$stateChangeSuccess
SET

10
Bence bu kabul edilen cevap olmalı. Olay iş olsa da $stateChangeSuccess, küresel düzeyde yapar, çoğu zaman gerçekten gerekli değildir.
Pierre Spring

2
Katılıyorum. Bu çok daha temiz. Tüm durumları olan birçok modülle uğraşıyorsanız, sadece modülünüzdekiler için değil, her durum değişikliği için $ stateChangeSuccess tetiklenir. Bunun için bir başka oy daha iyi çözümdür.
Jason Buchanan

1
@ Nissassin17 Hangi sürümü kullanıyorsunuz? Bir durum açarken v0.2.15, doğrudan doğruya $state.currentnesnesidir: {name: "", url: "^", views: null, abstract: true}.
Endy Tjahjono

3
FYI - Aşağıdakileri yapmam gerekiyordu: Params: angular.copy ($ state.params) - Açıklama: UI-Router v 1.0.0-beta 2 kullanıyorum ve bu kodun Params bölümü ile ilgili sorunlar yaşıyordum; $ state.params bir nesne olduğundan, işlev çözüldükten sonra geçerli görünüme güncellenecektir ... i nesnenin geçerli görünümde güncelleştirilmesini önlemek için bunu çözüm işlevinde yapmanız gerekiyordu.
Joe H

100

Okunabilirlik adına, çözümümü (stu.salsbury'nin anwser'ına dayanarak) buraya yerleştireceğim.

Bu kodu uygulamanızın soyut şablonuna ekleyin, böylece her sayfada çalışır.

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

RootScope'taki değişikliklerin kaydını tutar. Oldukça kullanışlı.


19
Eğer gerçekten birisini geldiği yere yönlendirmek istiyorsanız, fromParams'ı saklamakta fayda var.
Yaron

Bunu seviyorum ve uygulamalarıma uyguluyorum. Teşekkürler
Fallenreaper

Gerçekten yararlı ... Daha da fazla localStorage kullanarak, previousState'i istediğiniz yere alabilirsiniz.
georgeos

14

Aşağıdaki örnekte bir decorator(yapılandırma aşamasında uygulama başına yalnızca bir kez çalışır) oluşturdum ve $statehizmete fazladan bir özellik eklediğinden , bu yaklaşım genel değişkenlere genel değişkenler $rootscopeeklemez ve diğer servislere ekstra bir bağımlılık eklemesini gerektirmez $state.

Örneğimde, bir kullanıcıyı zaten oturum açtığında ve oturum açtıktan sonra bir önceki "korumalı" sayfaya yönlendirmeyeceği zaman dizin sayfasına yönlendirmek gerekiyordu.

Kullandığım tek bilinmeyen hizmetler (sizin için) authenticationFactoryve appSettings:

  • authenticationFactorysadece kullanıcı girişini yönetir. Bu durumda, kullanıcının oturum açıp açmadığını belirlemek için yalnızca bir yöntem kullanın.
  • appSettingsher yerde dizgiyi kullanmamak için sabitlerdir. appSettings.states.loginve appSettings.states.registergiriş ve kayıt URL'sinin durumunun adını içerir.

Daha sonra herhangi bir controller/ serviceetc'de $stateservis enjekte etmeniz gerekir ve mevcut ve önceki url'ye şu şekilde erişebilirsiniz:

  • Güncel: $state.current.name
  • Önceki: $state.previous.route.name

Chrome konsolundan:

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

Uygulama:

(Kullanıyorum angular-ui-router v0.2.17ve 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);

12

$ StateChangeStart üzerindeki $ state'a {previous} adlı yeni bir mülk ekleyin

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

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

Artık ihtiyacınız olan her yerde daha önce kullanabileceğiniz $ state kullanabilirsiniz

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

Ve şu şekilde kullanın:

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

9

Aynı sorunla sıkışıp kaldım ve bunu yapmanın en kolay yolunu buluyorum ...

//Html
<button type="button" onclick="history.back()">Back</button>

VEYA

//Html
<button type="button" ng-click="goBack()">Back</button>

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

(Daha test edilebilir olmasını istiyorsanız, $ window hizmetini kumandanıza enjekte edin ve $ window.history.back () kullanın.)


uygulamanızda menü varken daha karmaşık
Swanand

sorununuzu alamıyorum lütfen daha fazla ayrıntı verin
NiRmaL

Eğer url içine itmezseniz $ stateParams kaybedeceksiniz, daha iyi bir çözüm $ rootScope önceki parametrelerinizi kaydetmek olduğunu, bundan alabilir ve geri dönmek için $ durumuna itebilirsiniz.
dangquang1020

Bu yanıtı uygulamak benim için en kolay.
Lalnuntluanga Chhakchhuak

8

Endy Tjahjono'nun yaptıklarına benzer bir yaklaşım kullanıyorum.

Yaptığım şey, bir geçiş yapmadan önce mevcut durumun değerini kaydetmek. Bir örnek görelim; geçişi tetikleyen her şeye benzediğinde yürütülen bir fonksiyonun içinde bunu hayal edin:

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

Buradaki anahtar, params nesnesidir (duruma gönderilecek parametrelerin haritası) -> { previousState : { name : $state.current.name } }

Not: Ben sadece $ state nesnesinin name özniteliğini "kaydediyorum", çünkü devlet kaydetmek için gereken tek şey olduğunu unutmayın. Fakat bütün devlet nesnesine sahip olabiliriz.

Sonra, "ne olursa olsun" şöyle tanımlandığını belirtin:

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

Burada kilit nokta params nesnesidir.

params : {
  previousState: null,
}

Sonra, bu devletin içinde, önceki durumu şu şekilde alabiliriz:

$state.params.previousState.name

6

İşte Chris Thielen ui-router- extras'tan gerçekten şık bir çözüm : $ previousState

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

previous, şuna benzer bir nesnedir: { state: fromState, params: fromParams }burada fromState önceki durumdur ve fromParams önceki durum parametreleridir.


1
16 Mayıs 2017'de Chris Thielen , proje için bir Kullanım Sonu Bildirimi ekledi : ui-router-extras.
Michael R

4

Tamam, burada partiye geç kaldığımı biliyorum, ama açısal için yeniyim. Buradaki John Papa stil rehberine uymaya çalışıyorum . Bunu tekrar kullanılabilir hale getirmek istedim, böylece bir blokta oluşturdum. İşte ben geldim:

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

Çekirdek modülü

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

Bu kodla ilgili herhangi bir eleştiri sadece bana yardımcı olacaktır, bu yüzden lütfen bu kodu nerede geliştirebileceğimi bana bildirin.


2

Bu işlevselliğe ihtiyacınız varsa ve birden fazla denetleyicide kullanmak istiyorsanız, bu, rota geçmişini izlemek için basit bir hizmettir:

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

Burada .module ('core') içindeki 'core', uygulamanızın / modülünüzün adı olacaktır. Hizmeti denetleyicinize bağımlı olarak talep edin, ardından denetleyicinizde şunları yapabilirsiniz:$scope.routeHistory = RouterTracker.getRouteHistory()


4
Sayfamda geçmişte önceki duruma giden bir gezinme düğmesi olsaydı, önceki duruma geçtikten sonra, geçmişe ekleyen stateChangeSuccess tetiklenir. Yani bu kod, 2 sayfa arasında gidip gelmek için sonsuz bir döngüye neden olmaz mı?
whatsTheDiff

1

Ben $ rootScope önceki durumları takip , bu yüzden ihtiyaç olduğunda ben sadece aşağıdaki kod satırını arayacaktır.

$state.go($rootScope.previousState);

In App.js :

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

1
Ben sadece from.name'den tasarruf etmek daha iyi olduğunu düşünüyorum. Bu şekilde, $ state.go ($ tootScope.previousState.name, $ tootScope.previousState.params) gibi bir şey yapmanız gerektiğinde de parametrelere sahip olacaksınız;
abelabbesnabi

0

UI-Router için (> = 1.0), StateChange olayları kullanımdan kaldırıldı. Tam taşıma kılavuzu için burayı tıklayın

UI-Router 1.0 ve sonraki sürümlerinde geçerli durumun önceki durumunu almak için:

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

-1

Gerçekten basit bir çözüm sadece $ state.current.name dizesini düzenlemek ve son 've sonrasındaki her şeyi kesmek'. - ana durumun adını alırsınız. Durumlar arasında çok fazla atlarsanız bu çalışmaz, çünkü sadece geçerli yolu geriye doğru ayrıştırır. Ancak eyaletleriniz gerçekte bulunduğunuz yere karşılık geliyorsa, bu işe yarar.

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

1
$state.go('^')bunu başaracak
james

Peki ya devlet parametreleri?
Tushar Shukla

-2

Durumu şu şekilde döndürebilirsiniz:

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

Bir örnek:

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

    };

})();

2
Ebeveyn olmayan bir eyaletten devlete erişiyorsanız bu iyi bir yanıt değildir. Sadece mevcut durumun ebeveynini istiyorsanız, işi yapar.
Maxime Lafarie

1
Bu $ state.go ("^") kullanmakla aynı şey değil mi?
Nathan Moinvaziri
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.