web-dev-qa-db-ja.com

Angular - ui-routerは以前の状態を取得します

現在の状態の前の状態を取得する方法はありますか?

例えば、前の状態が現在の状態Bの前に何があったのか(前の状態が状態Aであったとしたら)を知りたいのです。

私はそれをui-router githubのドキュメントページで見つけることができません。

146
Mihai H

ui-routerは一度遷移すると前の状態を追跡しませんが、状態が変わるとイベント$stateChangeSuccess$rootScope上でブロードキャストされます。

そのイベントから前の状態をキャッチすることができるはずです(fromはあなたが去る状態です):

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

新しい状態に移行する前に現在の状態データを保存するためにresolveを使用します。

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

読みやすくするために、ここで私の解決策(stu.salsburyの助言者に基づく)を配置します。

このコードをアプリの抽象テンプレートに追加して、すべてのページで実行されるようにします。

$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の変更を追跡します。それはとても便利です。

96
Federico

次の例では、decoratorを作成し(設定フェーズでアプリごとに1回だけ実行)、$stateサービスに追加のプロパティを追加します。したがって、この方法ではグローバルは追加されません$rootscopeへの変数。$state以外の他のサービスへの追加の依存関係を追加する必要はありません。

私の例では、私は彼がすでにサインインしていたとき、そして彼がサインイン後に前の "保護された"ページにリダイレクトしないときにユーザーをインデックスページにリダイレクトする必要がありました。

私が使用する唯一の未知のサービス(あなたにとって)はauthenticationFactoryappSettingsです。

  • authenticationFactoryはユーザーログインを管理するだけです。この場合、私はユーザーがログインしているかどうかを識別するための方法だけを使います。
  • appSettingsは、あちこちで文字列を使わないための定数です。 appSettings.states.loginおよびappSettings.states.registerには、ログインおよび登録URLの状態の名前が含まれています。

それからcontroller/serviceなどでは$stateサービスを注入する必要があり、現在と以前のURLにアクセスすることができます。

  • 最新:$state.current.name
  • Previous:$state.previous.route.name

Chromeコンソールから:

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

実装:

(私はangular-ui-router v0.2.17angularjs 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

$ stateChangeStartの$ stateに{previous}という新しいプロパティを追加します。

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

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

今すぐあなたが必要とするところはどこでもあなたが前に利用可能になるであろう$ stateを使うことができます

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

そしてそれを次のように使います。

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

私は同じ問題に立ち往生しているし、これを行うための最も簡単な方法を見つけます...

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

(もっとテストしやすいようにしたい場合は、$ windowサービスをコントローラにインジェクトし、$ window.history.back()を使用してください)。

8
ProCylon

私はEndy Tjahjonoがすることと同じようなアプローチを使います。

私がすることは、移行をする前に現在の状態の値を保存することです。例を見てみましょう。これがトランジションの引き金となるものすべてに急上昇するときに実行される関数の内側で想像してみてください。

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

ここで重要なのはparamsオブジェクト(状態に送信されるパラメータのマップ)です - > { previousState : { name : $state.current.name } }

注:Imは$ stateオブジェクトのname属性を「保存」するだけであることに注意してください。これは、状態を保存するために必要な唯一のものだからです。しかし、私たちは州全体のオブジェクトを持つことができます。

それから、「何でも」が次のように定義されたと述べます。

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

ここでの要点はparamsオブジェクトです。

params : {
  previousState: null,
}

そして、その状態の中で、次のように前の状態を取得できます。

$state.params.previousState.name
8
avcajaraville

これはChris Thielenによる本当に優雅な解決策です i-router-extras:$ previousState

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

previousは、次のようなオブジェクトです。{ state: fromState, params: fromParams }ここで、fromStateは前の状態、fromParamsは前の状態パラメータです。

6
Ephraim

わかりました、私はここのパーティーに遅刻していることを知っています、しかし私は角度があるのが初めてです。私はこれを John Papa style guide に合わせるようにしています。これを再利用可能にしたかったので、ブロックで作成しました。これが私が思いついたものです:

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

このコードについての批判は私を助けてくれるだけなので、私がこのコードをどこで改善できるか教えてください。

4
fizch

この機能が必要で、複数のコントローラで使用したい場合、これはルート履歴を追跡するための簡単なサービスです。

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

ここで、.module( 'core')の 'core'は、あなたのアプリ/モジュールの名前になります。あなたのコントローラへの依存関係としてサービスを必要とし、そしてあなたのコントローラであなたがすることができます:$scope.routeHistory = RouterTracker.getRouteHistory()

2
user1970565

前の状態を$ rootScopeで追跡しているので、必要に応じて次のコード行を呼び出します。

$state.go($rootScope.previousState);

In App.js

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

UI-Router(> = 1.0)の場合、StateChangeイベントは非推奨になりました。完全な移行ガイドについては、 こちら をクリックしてください。

UI-Router 1.0以降で現在の状態の前の状態を取得するには:

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