現在の状態の前の状態を取得する方法はありますか?
例えば、前の状態が現在の状態Bの前に何があったのか(前の状態が状態Aであったとしたら)を知りたいのです。
私はそれをui-router githubのドキュメントページで見つけることができません。
ui-routerは一度遷移すると前の状態を追跡しませんが、状態が変わるとイベント$stateChangeSuccess
は$rootScope
上でブロードキャストされます。
そのイベントから前の状態をキャッチすることができるはずです(from
はあなたが去る状態です):
$rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
//assign the "from" parameter to something
});
新しい状態に移行する前に現在の状態データを保存するために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;
}]
}
});
}]);
読みやすくするために、ここで私の解決策(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の変更を追跡します。それはとても便利です。
次の例では、decorator
を作成し(設定フェーズでアプリごとに1回だけ実行)、$state
サービスに追加のプロパティを追加します。したがって、この方法ではグローバルは追加されません$rootscope
への変数。$state
以外の他のサービスへの追加の依存関係を追加する必要はありません。
私の例では、私は彼がすでにサインインしていたとき、そして彼がサインイン後に前の "保護された"ページにリダイレクトしないときにユーザーをインデックスページにリダイレクトする必要がありました。
私が使用する唯一の未知のサービス(あなたにとって)はauthenticationFactory
とappSettings
です。
authenticationFactory
はユーザーログインを管理するだけです。この場合、私はユーザーがログインしているかどうかを識別するための方法だけを使います。appSettings
は、あちこちで文字列を使わないための定数です。 appSettings.states.login
およびappSettings.states.register
には、ログインおよび登録URLの状態の名前が含まれています。それからcontroller
/service
などでは$state
サービスを注入する必要があり、現在と以前のURLにアクセスすることができます。
$state.current.name
$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.17
と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);
$ 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 );
私は同じ問題に立ち往生しているし、これを行うための最も簡単な方法を見つけます...
//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()を使用してください)。
私は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
これはChris Thielenによる本当に優雅な解決策です i-router-extras:$ previousState
var previous = $previousState.get(); //Gets a reference to the previous state.
previous
は、次のようなオブジェクトです。{ state: fromState, params: fromParams }
ここで、fromStateは前の状態、fromParamsは前の状態パラメータです。
わかりました、私はここのパーティーに遅刻していることを知っています、しかし私は角度があるのが初めてです。私はこれを 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
}
})();
このコードについての批判は私を助けてくれるだけなので、私がこのコードをどこで改善できるか教えてください。
この機能が必要で、複数のコントローラで使用したい場合、これはルート履歴を追跡するための簡単なサービスです。
(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()
前の状態を$ rootScopeで追跡しているので、必要に応じて次のコード行を呼び出します。
$state.go($rootScope.previousState);
In App.js:
$rootScope.$on('$stateChangeSuccess', function(event, to, toParams, from, fromParams) {
$rootScope.previousState = from.name;
});
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');
});
});