回答:
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;
}]
}
});
}]);
$stateChangeSuccess
$stateChangeSuccess
機能しますが、それはグローバルレベルで行われますが、ほとんどの場合は必要ありません。
$state.current
isオブジェクト:になり{name: "", url: "^", views: null, abstract: true}
ます。
読みやすくするために、ここにソリューション(stu.salsburyのanwserに基づく)を配置します。
このコードをアプリの抽象テンプレートに追加して、すべてのページで実行できるようにします。
$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>
または
//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オブジェクトの名前属性を「保存」することに注意してください。しかし、状態オブジェクト全体を持つことができます。
次に、「何でも」という状態を次のように定義します。
.state( 'user-edit', {
url : 'whatever'
templateUrl : 'whatever',
controller: 'whateverController as whateverController',
params : {
previousState: null,
}
});
ここで重要なのはparamsオブジェクトです。
params : {
previousState: null,
}
次に、その状態内で、次のように前の状態を取得できます。
$state.params.previousState.name
これは、Chris Thielen ui-router-extrasによる本当にエレガントなソリューションです。$ previousState
var previous = $previousState.get(); //Gets a reference to the previous state.
previous
は、次のようなオブジェクトです。{ state: fromState, params: fromParams }
ここで、fromStateは前の状態で、fromParamsは前の状態のパラメータです。
わかりました、私はここのパーティーに遅れるのを知っています、しかし私は角張ったことが初めてです。これをジョンパパスタイルガイドに合わせるようにしています。これを再利用可能にしたかったので、ブロックで作成しました。これが私が思いついたものです:
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);
では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');
});
});
本当に簡単な解決策は、$ state.current.name文字列を編集して、最後の「。」以降をすべて削除することです。-親の状態の名前を取得します。これは、現在のパスを解析するだけなので、状態間を頻繁にジャンプする場合は機能しません。しかし、あなたの州があなたが実際にいる場所に対応しているなら、これはうまくいきます。
var previousState = $state.current.name.substring(0, $state.current.name.lastIndexOf('.'))
$state.go(previousState)
$state.go('^')
これを達成します
この方法で状態を返すことができます:
$state.go($state.$current.parent.self.name, $state.params);
例:
(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);
};
};
})();