มีวิธีรับสถานะก่อนหน้าของสถานะปัจจุบันหรือไม่
ตัวอย่างเช่นฉันต้องการทราบว่าสถานะก่อนหน้านี้คืออะไรก่อนสถานะปัจจุบัน B (โดยที่สถานะก่อนหน้านี้จะเป็นสถานะ A)
ฉันไม่สามารถหามันได้ในหน้า ui-router github doc
มีวิธีรับสถานะก่อนหน้าของสถานะปัจจุบันหรือไม่
ตัวอย่างเช่นฉันต้องการทราบว่าสถานะก่อนหน้านี้คืออะไรก่อนสถานะปัจจุบัน B (โดยที่สถานะก่อนหน้านี้จะเป็นสถานะ A)
ฉันไม่สามารถหามันได้ในหน้า ui-router github doc
คำตอบ:
ui-router ไม่ได้ติดตามสถานะก่อนหน้านี้เมื่อมีการเปลี่ยน แต่เหตุการณ์$stateChangeSuccess
จะออกอากาศใน$rootScope
เมื่อสถานะเปลี่ยนไป
คุณควรจะสามารถจับสถานะก่อนหน้าจากเหตุการณ์นั้น ( from
คือสถานะที่คุณกำลังจะออก):
$rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
//assign the "from" parameter to something
});
ฉันใช้การแก้ไขเพื่อบันทึกข้อมูลสถานะปัจจุบันก่อนที่จะย้ายไปยังสถานะใหม่:
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
{name: "", url: "^", views: null, abstract: true}
เพื่อประโยชน์ในการอ่านฉันจะวางทางออกของฉัน (ตาม anwser ของ 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
(วิ่งเพียงครั้งเดียวต่อแอปเฟสการตั้งค่า) และเพิ่มคุณสมบัติพิเศษในการ$state
บริการดังนั้นวิธีการนี้จะไม่เพิ่มระดับโลกตัวแปร$rootscope
และไม่ต้องการที่จะเพิ่มการพึ่งพาพิเศษใด ๆ ในการบริการอื่น ๆ $state
กว่า
ในตัวอย่างของฉันฉันต้องการเปลี่ยนเส้นทางผู้ใช้ไปยังหน้าดัชนีเมื่อเขาลงชื่อเข้าใช้แล้วและเมื่อเขาไม่ได้เปลี่ยนเส้นทางเขาไปยังหน้า "ป้องกัน" ก่อนหน้าหลังจากลงชื่อเข้าใช้
บริการที่ไม่รู้จักเท่านั้น (สำหรับคุณ) ที่ฉันใช้คือauthenticationFactory
และappSettings
:
authenticationFactory
เพียงจัดการล็อกอินของผู้ใช้ ในกรณีนี้ฉันใช้วิธีการเฉพาะเพื่อระบุว่าผู้ใช้เข้าสู่ระบบหรือไม่appSettings
ค่าคงที่เพียงเพื่อไม่ใช้สตริงทุกที่ appSettings.states.login
และappSettings.states.register
มีชื่อของรัฐสำหรับการเข้าสู่ระบบและการลงทะเบียน URLจากนั้นในcontroller
/ service
etc ใดๆ คุณต้องใช้$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);
เพิ่มคุณสมบัติใหม่ที่เรียกว่า {previous} ไปยัง $ state บน $ stateChangeStart
$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 } }
หมายเหตุ: โปรดทราบว่าฉันเพียงแค่ "บันทึก" แอตทริบิวต์ชื่อของวัตถุ $ 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 เป็นพารามิเตอร์สถานะก่อนหน้า
ตกลงฉันรู้ว่าฉันมางานปาร์ตี้ที่นี่ช้า แต่ฉันใหม่สำหรับเชิงมุม ฉันกำลังพยายามทำให้พอดีกับคำแนะนำแบบ John Papaที่นี่ ฉันต้องการทำให้สามารถใช้ซ้ำได้ดังนั้นฉันจึงสร้างเป็นบล็อก นี่คือสิ่งที่ฉันมาด้วย:
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;
}
})();
โดยที่ '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);
};
};
})();