AngularJS UI राउटर - स्थिति को पुनः लोड किए बिना url बदलें


134

वर्तमान में हमारी परियोजना डिफ़ॉल्ट का उपयोग कर रही है $routeProvider, और मैं इस "हैक" का उपयोग कर रहा हूं, urlपृष्ठ को फिर से लोड किए बिना बदलने के लिए :

services.service('$locationEx', ['$location', '$route', '$rootScope', function($location, $route, $rootScope) {
    $location.skipReload = function () {
        var lastRoute = $route.current;
        var un = $rootScope.$on('$locationChangeSuccess', function () {
            $route.current = lastRoute;
            un();
        });
        return $location;
    };
    return $location;
}]);

और में controller

$locationEx.skipReload().path("/category/" + $scope.model.id).replace();

मैं घोंसले के शिकार मार्गों के routeProviderसाथ बदलने के बारे में सोच रहा हूं ui-router, लेकिन यह अंदर नहीं मिल सकता है ui-router

क्या यह संभव है - के साथ भी ऐसा ही करें angular-ui-router?

मैं इसकी क्या जरूरत है? मुझे एक उदाहरण के साथ समझाता हूं:
नई श्रेणी बनाने के लिए मार्ग SAVE I शो के /category/new बाद है और मैं मार्ग को बदलना चाहता हूं (23 - db में संग्रहीत नई आइटम की आईडी है)clickingsuccess-alert/category/new/caterogy/23


1
यूआई-राउटर में आपको प्रत्येक राज्यों के लिए एक URL को परिभाषित नहीं करना है, आप URL बदलने के बिना एक राज्य से दूसरे राज्य में नेविगेट कर सकते हैं
जोनाथन डी। एम।

क्या आप संपूर्ण URL या केवल खोज पथ अपडेट करना चाहते हैं? मैं खोज पथ को अपडेट करने वाले समाधान की खोज कर रहा था और इसे यहां पाया गया: stackoverflow.com/questions/21425378/…
फ्लोरियन लोच

@ जोनाथन वास्तव में? मैं ऐसा करना पसंद करूंगा, केवल एक URL दिखा रहा हूं, लेकिन $urlRouterProvider.otherwiseएक राज्य नहीं, बल्कि एक URL पर काम करता हूं । हम्म, शायद मैं 2 URL के साथ रह सकता हूं, या यह इंगित करने के लिए कोई अन्य तरीका ढूंढ सकता हूं कि यह अमान्य URL है।
मावग का कहना है कि मोनिका

जवाबों:


164

बस आप $state.transitionTo इसके बजाय उपयोग कर सकते हैं $state.go । आंतरिक रूप से $state.go कॉल $state.transitionTo करता है, लेकिन स्वचालित रूप से विकल्प सेट करता है { location: true, inherit: true, relative: $state.$current, notify: true } । आप कॉल $state.transitionTo और सेट कर सकते हैं notify: false । उदाहरण के लिए:

$state.go('.detail', {id: newId}) 

द्वारा प्रतिस्थापित किया जा सकता है

$state.transitionTo('.detail', {id: newId}, {
    location: true,
    inherit: true,
    relative: $state.$current,
    notify: false
})

संपादित करें: जैसा कि fracz द्वारा सुझाया गया है, यह बस हो सकता है:

$state.go('.detail', {id: newId}, {notify: false}) 

16
क्या "राज्य को पुनः लोड करते समय url न रखें" "पुनः लोडिंग राज्य के बिना url बदलें" के बजाय?
पीटर हेडबर्ग

25
मेरे लिए यह निम्नलिखित के साथ काम करता है: $state.transitionTo('.detail', {id: newId}, { location: true, inherit: true, relative: $state.$current, notify: false }) इसलिए मूल रूप से झूठे और सही स्थान पर सूचित करें
Arjen de Vries

6
@ArjendeVries हाँ यह उम्मीद के मुताबिक काम कर रहा है लेकिन मुझे एक अप्रत्याशित व्यवहार मिला। जब आप अंत में एक नए राज्य (यानी। url) के लिए आगे बढ़ रहे हैं, तो कई ट्रांस्फोर्मेंट विधि कॉल (फिर से लोड किए बिना) के साथ खेलने के बाद, यह पुराने नियंत्रक को फिर से शुरू करता है।
प्रेमचंद्र सिंह

2
@ प्रेमचंद्र सिंह: यहां भी यही मुद्दा रहा। राज्य से बाहर निकलते समय, पुराने नियंत्रक को फिर से आरंभ किया जाता है। मुझे वही समस्या wiherek से स्वीकृत समाधान के साथ मिलती है। यहाँ भी देखें github.com/angular-ui/ui-router/issues/64
martinoss

15
और भी सरल $state.go('.detail', {id: newId}, {notify: false}):।
फ़रक्ज़

48

ठीक है, हल किया गया :) कोणीय यूआई राउटर में यह नई विधि है, $ urlRouterProvider.deferIntercept () https://github.com/angular-ui/ui-router/issues/64

मूल रूप से यह नीचे आता है:

angular.module('myApp', [ui.router])
  .config(['$urlRouterProvider', function ($urlRouterProvider) {
    $urlRouterProvider.deferIntercept();
  }])
  // then define the interception
  .run(['$rootScope', '$urlRouter', '$location', '$state', function ($rootScope, $urlRouter, $location, $state) {
    $rootScope.$on('$locationChangeSuccess', function(e, newUrl, oldUrl) {
      // Prevent $urlRouter's default handler from firing
      e.preventDefault();

      /** 
       * provide conditions on when to 
       * sync change in $location.path() with state reload.
       * I use $location and $state as examples, but
       * You can do any logic
       * before syncing OR stop syncing all together.
       */

      if ($state.current.name !== 'main.exampleState' || newUrl === 'http://some.url' || oldUrl !=='https://another.url') {
        // your stuff
        $urlRouter.sync();
      } else {
        // don't sync
      }
    });
    // Configures $urlRouter's listener *after* your custom listener
    $urlRouter.listen();
  }]);

मुझे लगता है कि यह विधि वर्तमान में केवल कोणीय यूआई रूटर के मास्टर संस्करण में शामिल है , एक वैकल्पिक मापदंडों के साथ (जो बहुत अच्छा है, बीटीडब्ल्यू)। इसे क्लोन करने और स्रोत से निर्मित करने की आवश्यकता है

grunt build

डॉक्स स्रोत से, साथ ही साथ सुलभ हैं

grunt ngdocs

(वे / साइट निर्देशिका में निर्मित) // README.MD में अधिक जानकारी

ऐसा करने का एक और तरीका लगता है, डायनेमिक पैरामीटर (जिसका मैंने उपयोग नहीं किया है)। नाेटेबले को कई क्रेडिट।


एक विचार के रूप में, यहां पर कोणीय UI रूटर के $ StateProvider में वैकल्पिक पैरामीटर दिए गए हैं, जिनका उपयोग मैंने उपरोक्त के साथ संयोजन में किया है:

angular.module('myApp').config(['$stateProvider', function ($stateProvider) {    

  $stateProvider
    .state('main.doorsList', {
      url: 'doors',
      controller: DoorsListCtrl,
      resolve: DoorsListCtrl.resolve,
      templateUrl: '/modules/doors/doors-list.html'
    })
    .state('main.doorsSingle', {
      url: 'doors/:doorsSingle/:doorsDetail',
      params: {
        // as of today, it was unclear how to define a required parameter (more below)
        doorsSingle: {value: null},
        doorsDetail: {value: null}
      },
      controller: DoorsSingleCtrl,
      resolve: DoorsSingleCtrl.resolve,
      templateUrl: '/modules/doors/doors-single.html'
    });

}]);

वह क्या करता है यह एक राज्य को हल करने की अनुमति देता है, भले ही एक भी परमेस गायब हो। एसईओ एक उद्देश्य है, पठनीयता दूसरा।

ऊपर के उदाहरण में, मैं चाहता था कि दरवाजे एक आवश्यक पैरामीटर हो। यह स्पष्ट नहीं है कि उन्हें कैसे परिभाषित किया जाए। यह कई वैकल्पिक मापदंडों के साथ ठीक काम करता है, लेकिन वास्तव में कोई समस्या नहीं है। चर्चा यहाँ है https://github.com/angular-ui/ui-router/pull/1032#issuecomment-4946090


ऐसा लगता है कि आपका वैकल्पिक पैरामीटर काम नहीं करता है। Error: Both params and url specicified in state 'state'। यह डॉक्स में कहता है कि यह अमान्य उपयोग भी है। थोड़ा सा निराशाजनक।
Rhys van der Waerden

1
क्या आपने गुरु से निर्माण किया? कृपया ध्यान दें कि इस बिंदु पर जब मैंने समाधान जोड़ा था, तो वैकल्पिक पैरामीटर केवल उस संस्करण में शामिल थे जिन्हें स्रोत से मैन्युअल रूप से बनाया जाना था। जब तक v.0.3 बाहर न हो जाए, इसे रिलीज़ में शामिल नहीं किया जाएगा।
wiherek

1
बस एक त्वरित नोट। Nateabele के लिए धन्यवाद वैकल्पिक पैरामीटर v0.2.11 में उपलब्ध हैं जो कुछ दिनों पहले ही जारी किया गया था।
रिच97

यह बहुत भ्रामक है: मैं $ urlRouterProvider.deferIntercept () का उपयोग कैसे करूं; ताकि मैं नियंत्रक को फिर से लोड किए बिना परमेस को अपडेट कर सकूं? यह वास्तव में मुझे वह नहीं दिखाता है। रन फ़ंक्शन के भीतर आप एक स्टेटमेंट का मूल्यांकन कर सकते हैं कि सिंक करने के लिए या नहीं सिंक करने के लिए लेकिन सभी के साथ मुझे काम करना है पुराने और नए यूआरएल। मुझे कैसे पता चलेगा कि यह एक ऐसा उदाहरण है, जहां मैं केवल इतना करना चाहता हूं कि केवल दो url के साथ काम करने के लिए params को अपडेट करें? क्या तर्क होगा .... (यदि पुराना राज्य और नया राज्य समान हैं तो नियंत्रक पुनः लोड नहीं करते?) मैं भ्रमित हूं।
btm1

सही है, मुझे लगता है कि यह उपयोग मामला नेस्टेड राज्यों के साथ था, मैं बच्चे की स्थिति को फिर से लोड नहीं करना चाहता था, इस प्रकार इंटरसेप्ट कर रहा था। मुझे लगता है कि अब मैं इसके बजाय पूर्ण लक्ष्यीकरण विचारों के साथ करूंगा, और राज्य के बारे में मेरे विचार को परिभाषित करने से मुझे पता नहीं चलेगा। वैसे भी, यह अभी भी अच्छा है। आप पूर्ण url प्राप्त करते हैं, अर्थात आप url से स्थिति का अनुमान लगा सकते हैं। और क्वेरी और पथ पैरामीटर, आदि। यदि आप राज्यों और यूआरएल के आसपास अपना ऐप बनाते हैं, तो यह जानकारी का एक बहुत कुछ है। रन ब्लॉक में आप सेवाओं आदि का उपयोग कर सकते हैं। क्या यह आपके प्रश्न का उत्तर देता है?
wiherek

16

इस मुद्दे के साथ बहुत समय बिताने के बाद, यहाँ मुझे काम करना है

$state.go('stateName',params,{
    // prevent the events onStart and onSuccess from firing
    notify:false,
    // prevent reload of the current state
    reload:false, 
    // replace the last record when changing the params so you don't hit the back button and get old params
    location:'replace', 
    // inherit the current params on the url
    inherit:true
});

अन्य समाधान मार्ग प्रदाता से संबंधित हैं। यह समाधान केस के लिए काम करता है, मेरी तरह, जहां मैं $ राज्यप्रोवाइडर का उपयोग कर रहा हूं और $ मार्गप्रोइडर का उपयोग नहीं कर रहा हूं।
ईजे संजय 20'15

@eeejay मूल रूप से केवल प्रश्न के लिए पूछा गया है ui-router, आप कैसे कह सकते हैं कि, अन्य समाधान के लिए काम कर रहे थे $routerProvider, $routeProviderऔर $stateProviderवास्तुकला में पूरी तरह से अलग हैं ..
पंकज पारकर

क्या होगा अगर हम इसके साथ काम करने के लिए बैक बटन नहीं चाहते हैं? मेरा मतलब है, बैक प्रेस पर पिछली स्थिति / url पर जाएं, एक ही राज्य में अलग-अलग
परमस के

मुझे लगता है, इस समाधान से ब्राउज़र वापस काम नहीं करेगा, क्योंकि हम
ui-

2
मैंने यह कोशिश की, और ऐसा लगता है कि $onInit()जब भी मैं उपयोग करता हूं मेरे घटक को हर बार बुलाया जाता है $state.go। मुझे 100% ठीक नहीं लगता।
कैरम

8

कॉलिंग

$state.go($state.current, {myParam: newValue}, {notify: false});

अभी भी नियंत्रक को फिर से लोड करेगा।

इससे बचने के लिए, आपको पैरामीटर को गतिशील घोषित करना होगा:

$stateProvider.state({
    name: 'myState',
    url: '/my_state?myParam',
    params: {
        myParam: {
          dynamic: true,
        }
    },
    ...
});

फिर आपको notifyफोन करने की भी जरूरत नहीं है

$state.go($state.current, {myParam: newValue})

पर्याप्त होता। Neato!

से प्रलेखन :

जब dynamicहै true, तो पैरामीटर मान में परिवर्तन के कारण राज्य में प्रवेश / निकास नहीं होगा। रिज़ॉल्यूशन को फिर से नहीं लाया जाएगा, और न ही फिर से लोड किया जाएगा।

[...]

यह यूआई के निर्माण के लिए उपयोगी हो सकता है जहां घटक स्वयं को अपडेट करता है जब परम मान बदलता है।


7

इस सेटअप ने मेरे लिए निम्नलिखित मुद्दों को हल किया:

  • Url को से अपडेट करते समय प्रशिक्षण नियंत्रक को दो बार नहीं बुलाया जाता .../है.../123
  • किसी अन्य राज्य में नेविगेट करते समय प्रशिक्षण नियंत्रक को फिर से आमंत्रित नहीं किया जा रहा है

राज्य विन्यास

state('training', {
    abstract: true,
    url: '/training',
    templateUrl: 'partials/training.html',
    controller: 'TrainingController'
}).
state('training.edit', {
    url: '/:trainingId'
}).
state('training.new', {
    url: '/{trainingId}',
    // Optional Parameter
    params: {
        trainingId: null
    }
})

राज्यों को आमंत्रित करना (किसी अन्य नियंत्रक से)

$scope.editTraining = function (training) {
    $state.go('training.edit', { trainingId: training.id });
};

$scope.newTraining = function () {
    $state.go('training.new', { });
};

प्रशिक्षण नियंत्रक

var newTraining;

if (!!!$state.params.trainingId) {

    // new      

    newTraining = // create new training ...

    // Update the URL without reloading the controller
    $state.go('training.edit',
        {
            trainingId : newTraining.id
        },
        {
            location: 'replace', //  update url and replace
            inherit: false,
            notify: false
        });     

} else {

    // edit

    // load existing training ...
}   

मैं एक समान रणनीति का उपयोग करने की कोशिश कर रहा था, लेकिन मेरे नियंत्रक को कभी भी एडिट पेज से ट्रेनगाइड का मूल्य नहीं मिलता है, कुछ भी जो मुझे वहां याद आ रहा है? मैंने URL से सीधे और ui-sref का उपयोग करके संपादन पृष्ठ तक पहुँचने का प्रयास किया। मेरा कोड बिल्कुल आपके जैसा है।
निखिल भंडारी

यह मेरे लिए काम करता है, और अब तक सबसे स्पष्ट समाधान है
OoDeLally

3

यदि आपको केवल url बदलने की आवश्यकता है, लेकिन परिवर्तन स्थिति को रोकें:

स्थान बदलें (यदि आप इतिहास में बदलना चाहते हैं तो जोड़ दें):

this.$location.path([Your path]).replace();

अपने राज्य में पुनर्निर्देशित रोकें:

$transitions.onBefore({}, function($transition$) {
 if ($transition$.$to().name === '[state name]') {
   return false;
 }
});

2

मैंने ऐसा कुछ समय पहले संस्करण में किया था: UI0- राउटर का v0.2.10 कुछ इस तरह से ::

$stateProvider
  .state(
    'home', {
      url: '/home',
      views: {
        '': {
          templateUrl: Url.resolveTemplateUrl('shared/partial/main.html'),
          controller: 'mainCtrl'
        },
      }
    })
  .state('home.login', {
    url: '/login',
    templateUrl: Url.resolveTemplateUrl('authentication/partial/login.html'),
    controller: 'authenticationCtrl'
  })
  .state('home.logout', {
    url: '/logout/:state',
    controller: 'authenticationCtrl'
  })
  .state('home.reservationChart', {
    url: '/reservations/?vw',
    views: {
      '': {
        templateUrl: Url.resolveTemplateUrl('reservationChart/partial/reservationChartContainer.html'),
        controller: 'reservationChartCtrl',
        reloadOnSearch: false
      },
      'viewVoucher@home.reservationChart': {
        templateUrl: Url.resolveTemplateUrl('voucher/partial/viewVoucherContainer.html'),
        controller: 'viewVoucherCtrl',
        reloadOnSearch: false
      },
      'addEditVoucher@home.reservationChart': {
        templateUrl: Url.resolveTemplateUrl('voucher/partial/voucherContainer.html'),
        controller: 'voucherCtrl',
        reloadOnSearch: false
      }
    },
    reloadOnSearch: false
  })


-6

मुझे नहीं लगता कि इसके लिए आपको ui- राउटर की आवश्यकता है। $ स्थान सेवा के लिए उपलब्ध दस्तावेज़ पहले पैराग्राफ़ में कहते हैं, "... $ स्थान में परिवर्तन ब्राउज़र पता बार में परिलक्षित होते हैं।" यह बाद में यह कहना जारी रखता है, "यह क्या नहीं करता है? यह ब्राउज़र URL बदलने पर पूर्ण पृष्ठ पुनः लोड नहीं करता है।"

तो, इस बात को ध्यान में रखते हुए, क्यों न केवल $ ठिकाना बदल दिया जाए ।पथ (जैसा कि विधि दोनों एक गटर और सेटर है) निम्न के साथ कुछ इस तरह से है:

var newPath = IdFromService;
$location.path(newPath);

प्रलेखन नोट पथ हमेशा फॉरवर्ड स्लैश के साथ शुरू करना चाहिए कि, लेकिन यह जोड़ देगा अगर यह याद आ रही है।


जब मैं उपयोग करता हूं ui-router, और उपयोग करता हूं $location.path(URL_PATH), तो पृष्ठ स्वचालित रूप से फिर से प्रस्तुत करता है ?!
कौषा जूल 8'14

हाँ, यह फिर से प्रस्तुत करता है। मैंने $ locationChangeStart पर event.preventDefault () के साथ कोशिश की, जो या तो काम नहीं करता है - अर्थात यह राज्य को फिर से प्रस्तुत करने से रोकता है, लेकिन यह url को अपडेट करने से भी रोकता है।
16
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.