कोणीय - यूआई-राउटर को पिछली स्थिति मिलती है


152

क्या वर्तमान राज्य की पिछली स्थिति को प्राप्त करने का कोई तरीका है?

उदाहरण के लिए, मैं यह जानना चाहूंगा कि वर्तमान राज्य B से पहले का राज्य क्या था (जहां पिछला राज्य राज्य A होगा)।

मैं इसे यूआई-राउटर जीथब डॉक पृष्ठों में नहीं पा रहा हूं।


नीचे उत्तर सही है आप स्रोत से अपनी जरूरत की सभी जानकारी भी पा सकते हैं यदि डॉक्स पर्याप्त मदद नहीं कर रहे हैं। go
David Chase

जवाबों:


133

यूआई-राउटर एक बार संक्रमण होने पर पिछले राज्य को ट्रैक नहीं करता है, लेकिन जब राज्य बदलता है , तो यह घटना $stateChangeSuccessप्रसारित होती है $rootScope

आपको उस घटना से पूर्व स्थिति को पकड़ने में सक्षम होना चाहिए ( fromवह राज्य है जिसे आप छोड़ रहे हैं):

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

3
"से" का उपयोग करके एक उदाहरण क्या होगा?
पॉल

यहाँ 'to' और 'from' का अर्थ 'toState' और 'fromState' है। अपने पिछले यूआरएल पर विचार करें लोकलहोस्ट: xxxx / कर्मचारी और कंट्रोलर 'एम्प्लॉईकॉन्ट्रोलर' है, फिर 'fromState' के लिए उदाहरण है: ऑब्जेक्ट {url: "/ कर्मचारी", templateUrl: "/ कर्मचारी", कंट्रोलर: "EmployeesController", नाम: " कर्मचारी "}
रणधीर रेड्डी

3
मैंने अपने सार में ऐसा किया: `$ rootScope.prepretState; $ rootScope.currentState; $ rootScope। $ पर ('$ StateChangeSuccess', फ़ंक्शन (ev, toParams, from, PPams से) {$ rootScope.prepretState = from.name; $ rootSopeope.currentState = to.name। कंसोल ('पिछला राज्य:) '+ $ rootScope.prepretState) कंसोल.log (' वर्तमान स्थिति: '+ $ rootScope.currentState)}); `यह रूटस्स्कोप में पिछले और वर्तमान का ट्रैक रखता है। बहुत आसान!
फेडेरिको

@ Endy-tjahjono ( stackoverflow.com/a/25945003/2837519 ) के समाधान का उपयोग करना ui- राउटर 1.x का अधिक इनलाइन है।
पीटर अहलर्स

मुझे history.back () <a href="javascript:history.back()" class="btn btn-default no-radius">
Serip88

146

मैं नए राज्य में जाने से पहले वर्तमान स्थिति डेटा को बचाने के लिए संकल्प का उपयोग करता हूं:

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
से निपटने की तुलना में बेहतर है$stateChangeSuccess
सेट

10
मेरी राय में, यह स्वीकृत उत्तर होना चाहिए। घटना हालांकि $stateChangeSuccessकाम करता है, यह एक वैश्विक स्तर पर करता है, जिसे वास्तव में अधिकांश समय की आवश्यकता नहीं होती है।
पियरे स्प्रिंग

2
मैं सहमत हूँ। यह बहुत क्लीनर है। यदि आप कई मॉड्यूलों के साथ काम कर रहे हैं जो सभी राज्यों में हैं, तो $ StateChangeSuccess को प्रत्येक राज्य परिवर्तन के लिए निकाल दिया जाएगा, न कि केवल आपके मॉड्यूल में। इसके लिए एक और वोट बेहतर उपाय है।
जेसन बुकानन

1
@ Nissassin17 आप किस संस्करण का उपयोग करते हैं? V0.2.15 में एक राज्य को सीधे खोलने $state.currentपर ऑब्जेक्ट है {name: "", url: "^", views: null, abstract: true}:।
एंडी तजहोनो

3
FYI करें - मुझे निम्नलिखित करने की आवश्यकता है: Params: angular.copy ($ state.params) - स्पष्टीकरण: मैं UI- राउटर v 1.0.0-beta 2 का उपयोग कर रहा हूं और मैं इस कोड के परमेस भाग के साथ समस्या कर रहा था; क्योंकि $ state.params एक ऑब्जेक्ट है, यह फ़ंक्शन के हल होने के बाद वर्तमान दृश्य में अपडेट होगा ... मुझे ऑब्जेक्ट को वर्तमान दृश्य में अपडेट होने से रोकने के लिए रिज़ॉल्यूशन फ़ंक्शन में ऐसा करने की आवश्यकता है।
जो एच।

100

पठनीयता की खातिर, मैं अपना समाधान (यहाँ stu.salsbury के awser के आधार पर) रखूँगा।

इस कोड को अपने ऐप के अमूर्त टेम्पलेट में जोड़ें ताकि यह हर पेज पर चले।

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

रूटस्स्कोप में परिवर्तनों का ट्रैक रखता है। इसका बहुत काम है।


19
यदि आप वास्तव में किसी को वापस भेजना चाहते हैं, तो यह किपर्म्स को स्टोर करना सार्थक है।
यार्न

मैं इसे प्यार करता हूं और इसे अपने अनुप्रयोगों में लागू करता हूं। धन्यवाद
फॉलेंप्रिपर

वास्तव में उपयोगी ... और भी अधिक स्थानीय स्तर का उपयोग करके, आप कहीं भी पिछले पा सकते हैं।
जॉर्जियो

14

निम्नलिखित उदाहरण में मैंने एक बनाया decorator(विन्यास चरण में केवल एक बार ऐप चलाता है) और $stateसेवा के लिए एक अतिरिक्त संपत्ति जोड़ता है , इसलिए यह दृष्टिकोण वैश्विक चर को नहीं जोड़ता है $rootscopeऔर इसके अलावा अन्य सेवाओं के लिए कोई अतिरिक्त निर्भरता जोड़ने की आवश्यकता नहीं है $state

मेरे उदाहरण में मुझे एक उपयोगकर्ता को इंडेक्स पेज पर पुनर्निर्देशित करने की आवश्यकता थी जब वह पहले ही साइन इन था और जब वह साइन इन करने के बाद पिछले "संरक्षित" पृष्ठ पर उसे रीडायरेक्ट नहीं करना चाहता था।

केवल अज्ञात सेवाएं (आपके लिए) जिनका मैं उपयोग कर रहा हूं authenticationFactoryऔर appSettings:

  • authenticationFactoryबस उपयोगकर्ता लॉगिन को प्रशासित करता है। इस मामले में, मैं केवल यह पता लगाने के लिए एक विधि का उपयोग करता हूं कि उपयोगकर्ता लॉग इन है या नहीं।
  • appSettingsबस हर जगह तार का उपयोग नहीं करने के लिए स्थिरांक हैं। appSettings.states.loginऔर appSettings.states.registerलॉगिन और रजिस्टर यूआरएल के लिए राज्य का नाम शामिल करें।

फिर किसी भी controller/ serviceआदि में आपको $stateसेवा को इंजेक्ट करने की आवश्यकता होती है और आप वर्तमान और पिछले यूआरएल को इस तरह एक्सेस कर सकते हैं:

  • वर्तमान: $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);

12

$ 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;
    ...
}

अब कहीं भी आपको $ स्थिति का उपयोग करने की आवश्यकता होगी जो आपके पास पहले उपलब्ध होगी

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

9

मैं एक ही मुद्दे के साथ फंस गया हूं और ऐसा करने का सबसे आसान तरीका ढूंढता हूं ...

//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.history.back ()) का उपयोग करें।


आपके आवेदन में मेनू होने पर यह अधिक जटिल है
स्वानंद

अपनी समस्या को नहीं
सुलझाते हुए

आप $ StateParams खो देंगे यदि आप इसे url में नहीं धकेलते हैं, तो बेहतर उपाय यह है कि आप अपने पिछले Params को $ rootScope में सेव करें, आप इसे उसी से प्राप्त कर सकते हैं और वापस जाने के लिए $ अवस्था में धकेल सकते हैं।
डंगक्वांग 1020

यह जवाब मेरे लिए लागू करना सबसे आसान है।
लालनुंटलुंगा छकछुक

8

मैं एक समान दृष्टिकोण का उपयोग करता हूं जो एंडी तजहोनो करता है।

संक्रमण करने से पहले मैं वर्तमान स्थिति के मूल्य को बचाने के लिए क्या कर रहा हूं। एक उदाहरण पर देखते हैं; संक्रमण के लिए जो भी ट्रिगर करता है, उस पर चढ़ाई करते समय निष्पादित फ़ंक्शन के अंदर इसकी कल्पना करें:

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

यहां कुंजी परम ऑब्जेक्ट है (मापदंडों का एक नक्शा जो राज्य को भेजा जाएगा) -> { previousState : { name : $state.current.name } }

नोट: ध्यान दें कि Im केवल "बचत" $ राज्य वस्तु का नाम विशेषता है, क्योंकि केवल एक चीज है जो मुझे राज्य को बचाने के लिए चाहिए। लेकिन हमारे पास पूरे राज्य की वस्तु हो सकती है।

फिर, राज्य "जो भी" इस तरह परिभाषित किया गया है:

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

यहाँ, मुख्य बिंदु परम वस्तु है।

params : {
  previousState: null,
}

फिर, उस राज्य के अंदर, हम पिछले राज्य को इस तरह प्राप्त कर सकते हैं:

$state.params.previousState.name

6

यहां क्रिस थिएलेन यूआई-राउटर-एक्स्ट्रा से एक बहुत ही सुंदर समाधान है : $ पूर्व

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

previousएक ऐसी वस्तु है, जो इस प्रकार दिखाई देती है: { state: fromState, params: fromParams }जहाँ fromState पिछला राज्य है और fromParams पिछला राज्य पैरामीटर है।


1
16 मई, 2017 को, क्रिस थिएलेन ने प्रोजेक्ट के लिए एंड ऑफ़ लाइफ नोटिस जोड़ा : ui-router-extras।
माइकल आर

4

ठीक है, मुझे पता है कि मुझे यहां पार्टी के लिए देर हो रही है, लेकिन मैं कोणीय के लिए नया हूं। मैं यहां जॉन पापा स्टाइल गाइड में इसे फिट करने की कोशिश कर रहा हूं । मैं इस पुन: प्रयोज्य बनाना चाहता था इसलिए मैंने एक ब्लॉक में बनाया। यहां वह है जो मैंने जुटाया:

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

इस कोड पर कोई भी आलोचना केवल मेरी मदद करेगी, इसलिए कृपया मुझे बताएं कि मैं इस कोड को कहां सुधार सकता हूं।


2

यदि आपको इस कार्यक्षमता की आवश्यकता है और इसे एक से अधिक नियंत्रक में उपयोग करना चाहते हैं, तो यह रूट इतिहास को ट्रैक करने के लिए एक सरल सेवा है:

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

जहाँ। कोर ('कोर') में 'कोर' आपके ऐप / मॉड्यूल का नाम होगा। अपने नियंत्रक पर निर्भरता के रूप में सेवा की आवश्यकता है, तो अपने नियंत्रक में आप कर सकते हैं:$scope.routeHistory = RouterTracker.getRouteHistory()


4
अगर मेरे पास मेरे पृष्ठ पर एक नेविगेशनल बटन है जो इतिहास में पिछले राज्य में जाता है, तो उस पूर्व स्थिति में नेविगेट करने के बाद, राज्यचेंजसुइट को निकाल दिया जाएगा जो इसे इतिहास में जोड़ता है। तो क्या यह कोड 2 पृष्ठों के बीच आगे और पीछे जाने के अंतहीन पाश में परिणत नहीं होगा?
whatsTheDiff

1

मैं $ rootScope में पिछले राज्यों का ट्रैक रखता हूं , इसलिए जब भी आवश्यकता होगी मैं सिर्फ कोड की निचली पंक्ति को कॉल करूंगा।

$state.go($rootScope.previousState);

में App.js :

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

1
मुझे लगता है कि यह बेहतर है यदि आप न केवल से बचाएं। इस तरह, आपके पास परमेस भी होंगे, अगर आपको $ state.go ($ tootScope.prepretState.name, $ tootScope.prepretState.params) जैसा कुछ करने की आवश्यकता है;
abelabbesnabi

0

यूआई-राउटर (> = 1.0) के लिए, स्टेटचेंज घटनाओं को हटा दिया गया है। पूर्ण माइग्रेशन गाइड के लिए, यहां क्लिक करें

UI- राउटर 1.0+ में वर्तमान स्थिति की पिछली स्थिति प्राप्त करने के लिए:

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

-1

वास्तव में एक सरल उपाय सिर्फ $ state.current.name स्ट्रिंग को संपादित करना है और अंतिम 'सहित' और बाद में सब कुछ काट देना है। - आपको मूल राज्य का नाम मिलता है। यदि आप राज्यों के बीच बहुत अधिक कूदते हैं तो यह काम नहीं करता है क्योंकि यह वर्तमान पथ को वापस पार्स करता है। लेकिन अगर आपके राज्य वास्तव में आप कहां हैं, तो यह काम करता है।

var previousState = $state.current.name.substring(0, $state.current.name.lastIndexOf('.'))
$state.go(previousState)

1
$state.go('^')पूरा होगा इस
जेम्स

और राज्य के बारे में क्या?
तुषार शुक्ला

-2

आप इस तरह से राज्य वापस कर सकते हैं:

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

    };

})();

2
यदि आप राज्य को गैर-अभिभावक राज्य से एक्सेस कर रहे हैं तो यह एक अच्छा जवाब नहीं है। यदि आप केवल वर्तमान स्थिति के माता-पिता चाहते हैं, तो यह काम करता है।
मैक्सिमे लाफ़ारी

1
क्या यह $ state.go ("^") का उपयोग करने के समान नहीं है?
नाथन मोइनवाज़िरी 20
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.