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.