(कोणीय-यूआई-राउटर) समाधान प्रक्रिया के दौरान लोडिंग एनीमेशन दिखाएं


80

यह एक दो भाग प्रश्न है:

  1. मैं नियंत्रक को लोड करने से पहले कुछ सर्वर डेटा को हथियाने के लिए $ stateProvider.state () के अंदर संकल्प संपत्ति का उपयोग कर रहा हूं। मैं इस प्रक्रिया के दौरान दिखाने के लिए लोडिंग एनीमेशन कैसे प्राप्त करूंगा?

  2. मेरे पास बाल राज्य हैं जो संकल्प संपत्ति का उपयोग करते हैं। समस्या यह है कि यूआई-राउटर किसी भी नियंत्रक को लोड करने से पहले सभी हल को अंतिम रूप देना चाहता है । क्या कोई तरीका है कि मैं माता-पिता के नियंत्रकों को लोड करने के लिए एक बार उनके हल को हल करने के लिए प्राप्त कर सकता हूं, बिना सभी बच्चे को हल करने के लिए इंतजार किए बिना? इसका उत्तर संभवतः पहली समस्या को भी हल करेगा।


4
क्या आपने कभी इस मुद्दे को हल किया?
स्टीफन हेन्ज

3
@StefanHenze नहीं, मैंने इसे केवल यूआई-राउटर वास्तु दोष के रूप में स्वीकार किया है।
मैट वे

2
इस सटीक समस्या के बारे में यहाँ चर्चा है: github.com/angular-ui/ui-router/issues/456
जॉनी ओशिका

6
@StefanHenze lol, कोई सज़ा का इरादा नहीं ....
डेव

जवाबों:


71

संपादित करें: यहाँ एक और भी आसान समाधान है, परीक्षण और अच्छी तरह से काम कर रहा है:

मेरे मुख्य नियंत्रक में मेरे पास बस है

$scope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
    if (toState.resolve) {
        $scope.showSpinner();
    }
});
$scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
    if (toState.resolve) {
        $scope.hideSpinner();
    }
});

यह स्पिनर को दिखाता है जब भी हम उस राज्य में जाने वाले होते हैं, जिसके पास समाधान करने के लिए कुछ भी होता है और इसे तब छुपाता है, जब राज्य परिवर्तन पूरा हो जाता है। आप राज्य पदानुक्रम को कुछ जांच जोड़ना चाहते हैं (यानी स्पिनर को भी दिखा सकते हैं यदि कोई मूल राज्य जो लोड किया जा रहा है, कुछ हल करता है) लेकिन यह समाधान मेरे लिए ठीक काम करता है।

यहाँ संदर्भ के लिए और एक विकल्प के रूप में मेरा पुराना सुझाव है:

  1. अपने एप्लिकेशन कंट्रोलर में, stateChangeStartईवेंट को सुनें और जांचें कि क्या आप उस स्थिति में स्विच करने जा रहे हैं, जहां आप समाधान के दौरान स्पिनर दिखाना चाहते हैं (देखें https://github.com/angular-ui/ui-router/wiki/Quick -Reference # विकी-इवेंट्स -1 )

    $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
        if (toState.name == 'state.with.resolve') {
            $scope.showSpinner();  //this is a function you created to show the loading animation
        }
    })
    
  2. जब आप नियंत्रक को अंततः बुलाते हैं, तो आप स्पिनर को छिपा सकते हैं

    .controller('StateWithResolveCtrl', function($scope) {
        $scope.hideSpinner();
    })
    

आप किसी भी त्रुटि के लिए भी जांच कर सकते हैं जो कि त्रुटि को हल करने के दौरान $stateChangeErrorघटना को सुनकर और एनीमेशन को छिपाकर हो सकती है।

यह पूरी तरह से साफ नहीं है क्योंकि आप स्पिनरों के लिए नियंत्रक के बीच तर्क वितरित करते हैं, लेकिन यह एक तरीका है। आशा है कि इससे सहायता मिलेगी।


1
if (toState.resolve)जाँचता है कि राज्य कॉन्फ़िगर में एक संकल्प शब्दकोश है। मेरे मामले में, यह एक अच्छा अनुमान है कि राज्य async सेवा कॉल करता है। मेरा मानना ​​है कि यदि कोई रिज़ॉल्यूशन ब्लॉक है, तो यह सेवा कॉल है जो हल हो जाती है। कोड केवल स्पिनर को दिखाता है और छिपाता है यदि सेवा कॉल किए गए थे। जैसा कि मैंने ऊपर वर्णित किया है, इस कोड को आपके उपयोग के मामले के आधार पर मूल राज्यों की जांच करने के लिए परिष्कृत करने की आवश्यकता हो सकती है।
स्टीफन हेन्ज

'पुराने सुझाव' में आप $scopeकॉल के अंदर संदर्भ देते हैं $rootScope। यहाँ कहाँ से $scopeआता है?
पीडीए

@pdeva, इवेंट हैंडलर को कुछ कंट्रोलर के अंदर परिभाषित किया गया था; वह भी जहां showSpinnerफ़ंक्शन को परिभाषित किया गया था।
स्टेफन हेन्ज

मैं उपयोग नहीं कर सका toState.resolveइसलिए मैंने उपयोग किया fromState.name !== toState.name। इसके अलावा आपका जवाब शानदार है, अच्छा किया!
जैकब हुल्स

22

मैंने निम्नलिखित समाधान विकसित किया जो मेरे लिए पूरी तरह से काम करता है।

1. निम्नलिखित एप्लिकेशन जोड़ें

app.run(function($rootScope){

    $rootScope
        .$on('$stateChangeStart', 
            function(event, toState, toParams, fromState, fromParams){ 
                $("#ui-view").html("");
                $(".page-loading").removeClass("hidden");
        });

    $rootScope
        .$on('$stateChangeSuccess',
            function(event, toState, toParams, fromState, fromParams){ 
                $(".page-loading").addClass("hidden");
        });

});

2. लोडिंग संकेतक को यूआई-व्यू के ठीक ऊपर रखें। Ui-view div में id = "ui-view" जोड़ें।

<div class="page-loading">Loading...</div>
<div ui-view id="ui-view"></div>

3. अपने सीएसएस में निम्नलिखित जोड़ें

.hidden {
  display: none !important;
  visibility: hidden !important;
}

ध्यान दें:

उ। उपरोक्त कोड दो मामलों में लोडिंग संकेतक प्रदर्शित करेगा 1) जब कोणीय ऐप पहली बार 2 लोड होता है ) जब दृश्य बदल जाता है।

ख। यदि आप नहीं चाहते हैं कि जब कोणीय ऐप पहली बार लोड हो (जब कोई दृश्य लोड होने से पहले) संकेतक दिखाया जाए, तो नीचे दिए गए लोडिंग डिव की तरह छिपा हुआ वर्ग जोड़ें

<div class="page-loading hidden">Loading...</div>

15
यह runकोड कोणीय मार्ग नहीं है। वहां DOM को मैनिपुलेट करने के बजाय, जैसे loadingVisibleऔर viewVisible, और फिर HTML में स्कोप वैरिएबल सेट करें , जब तत्व दिखाई दे रहे हों या छिपे हों, जैसे <div class="page-loading" ng-show="viewVisible">Loading...</div>:। दृश्य को खाली करने के लिए हालांकि इसे एक कस्टम निर्देश की आवश्यकता हो सकती है।
मथायस

2
यह अनुशंसित नहीं है। Angularcontext के अंदर jQuery का उपयोग करना बुरा है और आपके विचार और नियंत्रक के बीच अवांछित निर्भरता पैदा कर रहा है - अच्छा अभ्यास नहीं!
सिलस हैनसेन

मुझे यह पसंद है लेकिन ... क्या यह वास्तव में डोम के संबंध में सही है?
contributorpw

@MatthiasDailey जैसे इस 'कोणीय तरीके' को करने के साथ मुद्दा यह है कि आपको शो / डुप्लीकेट लॉजिक को पूरे स्थान पर डुप्लिकेट करने की आवश्यकता होगी। इस समाधान के बारे में साफ बात यह है कि आपके पास सामग्री या लोडर को दिखाने / छिपाने के लिए एक वैश्विक तरीका हो सकता है। यदि आप वास्तव में इस कोणीय तरीके से करना चाहते हैं, तो एक नया निर्देश बनाएं, जो ui-view
thomaux

1
मुझे लगता है कि एनजी-क्लास इस के लिए एक बेहतर दृष्टिकोण होगा।
UserX


8

गुण को हल करने के बाद यूआई-राउटर द्वारा भरे जाने वाले डिव में सामग्री जोड़ने के बारे में कैसे?

अपने में index.html

<div ui-view class="container">
    Loading....
</div>

अब उपयोगकर्ता "लोड हो रहे हैं ..." देखेंगे जबकि गुणों का समाधान किया जाता है। एक बार जब सब कुछ तैयार हो जाता है तो सामग्री आपके ऐप्स सामग्री के साथ यूआई-राउटर द्वारा बदल दी जाएगी।


7
यह काम करेगा यदि आपके एप्लिकेशन में पूर्ण ऐप लोडिंग रिप्लेसमेंट हो सकता है, लेकिन अगर आप अपने लोडिंग ... 'को अपने लेआउट में क्रमबद्ध करना चाहते हैं (जैसे आपके एप्लिकेशन शो का कुछ हिस्सा लोड हो रहा है, तो एक और हिस्सा लोड हो रहा है ... ) है।
मैट वे

1
यह अभी भी एक त्वरित / गंदा / आसान तरीका है जिससे आप अधिक महत्वपूर्ण चीजों पर आगे बढ़ सकते हैं ... जैसे कि आपके रिज़ॉल्यूशन को गति देना।
ब्रायन वेंडरबस

3
यदि आप उस दृश्य में कई टेम्पलेट लोड कर रहे हैं, जो आदर्श रूप से आप चाहते हैं। "लोडिंग ...." संदेश केवल पहली बार दिखाई देगा।
यासिर शेख

क्या यह आयोनिक में संभव है? मैं इओनिक में इस तरह का उपयोग करने में सक्षम नहीं था।
अनूप डेब

7

मैं एक एनिमेटेड gif का उपयोग करता हूं जिसे मैं केवल तभी दिखाता हूं जब $httpलंबित अनुरोध होते हैं।

मेरे बेस पेज टेम्प्लेट में, मेरे पास एक नेबर और नेवबार कंट्रोलर है। नियंत्रक का प्रासंगिक हिस्सा इस तरह दिखता है:

controllers.controller('NavbarCtrl', ['$scope', '$http',
    function ($scope, $http) {
        $scope.hasPendingRequests = function () {
            return $http.pendingRequests.length > 0;
        };
    }]);

मेरे HTML में संबंधित कोड है:

<span class="navbar-spinner" ng-show="hasPendingRequests()">
    <img src="/static/img/spinner.gif">
</span>

मुझे आशा है कि वह मदद करेंगे!


3
जैसा कि आप मेरे सवाल से देख सकते हैं, मेरे पास नियंत्रकों तक कोई पहुंच नहीं है जब तक कि सभी हल अंतिम रूप नहीं दिए गए हैं (जो कि समस्या है)!
मैट वे

1
आपको एनजी-शो या एनजी-अगर के लिए फ़ंक्शन का उपयोग नहीं करना चाहिए, क्योंकि उन्हें प्रत्येक डाइजेस्ट लूप में कहा जाएगा। इससे प्रदर्शन में कमी आएगी।
विकास गौतम

4

मेरा विचार संक्रमण वाले राज्यों के बीच राज्य के ग्राफ पर पथ पर चलना है $stateChangeStartऔर सभी शामिल विचारों को इकट्ठा करना है। तब प्रत्येक ui-viewनिर्देश देखता है कि क्या संबंधित दृश्य संक्रमण में शामिल है और 'ui-resolving'यह तत्व पर वर्ग जोड़ता है।

Plunker डेमो दो जड़ राज्यों का परिचय: firstऔर second, बाद के दो substates है second.sub1और second.sub2। राज्य उस second.sub2लक्ष्य को भी footerदेखता है जो उसके दादा-दादी का है।


3

यह किसी भी राज्य (किसी भी पेज), app.js में डाल के बीच नेविगेट करते समय विश्व स्तर पर लोडर है

.run(
    ['$rootScope',
        function($rootScope) {
            $rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
                $rootScope.preloader = true;
            })
            $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
                $rootScope.preloader = false;
            })
        }
    ])

Html में:

<div ng-show="preloader">Loading...</div>

उत्तम! धन्यवाद!
ब्रायनर फेरेरा

अधिक स्पष्ट नहीं हो सकता ... शायद यह बताएं कि लोडिंग प्रगति पर है, तो आप ui-view में कुछ कैसे डाल सकते हैं? 2 चर को परिभाषित करना बहुत तुच्छ है
DDD

2

मैं किसी भी लोडिंग गतिविधि से मेल खाने के निर्देश का उपयोग करना पसंद करता हूं, मुख्य रूप से अपने कोडबेस को साफ रखने के लिए

angular.module('$utilityElements', [])
.directive('loader',['$timeout','$rootScope', function($timeout, $rootScope) {
    return {
      restrict: 'A',
      template: '<div id="oneloader" class="hiddenload">loading...</div>',
      replace: true,
      compile: function (scope, element, attrs) {
        $timeout(function(){
          $rootScope
              .$on('$stateChangeStart',
                  function(event, toState, toParams, fromState, fromParams){
                      $("#oneloader").removeClass("hiddenload");
              });

          $rootScope
              .$on('$stateChangeSuccess',
                  function(event, toState, toParams, fromState, fromParams){
                      //add a little delay
                      $timeout(function(){
                        $("#oneloader").addClass("hiddenload");
                      },500)
              });
        }, 0);
      }
    }
  }]);

2

के $stateChangeStartबाद से और इसके जैसे उपयोग को हटा दिया गया है और संक्रमण हुक के साथ बदल दिया गया है । तो, स्टीफन हेनज़ द्वारा जवाब के लिए, अद्यतन संस्करण होगा:

$transitions.onStart({}, function(transition) {
  if (transition.to().resolve) {
    $scope.showSpinner();
  }
});

$transitions.onSuccess({}, function(transition) {
  if (transition.to().resolve) {
    $scope.hideSpinner();
  }
});

इसका उपयोग आप पेरेंट कंट्रोलर में कर सकते हैं। इंजेक्ट करना याद रखें $transitions-

.controller('parentController',['$transitions',function($transitions){...}]);

इसके अलावा, ध्यान रखें कि resolveयह एक खाली वस्तु है जो अभी भी प्रस्तुत करेगा transition.to().resolve == true, इसलिए resolveराज्य घोषणा में एक खाली प्लेसहोल्डर न छोड़ें ।


1

राउटर में रेसोल का उपयोग करते समय दृश्य का उपयोग करने के लिए मेरा आइडिया यह कमाल का काम कर रहा है। इसे इस्तेमाल करे।

//edit index.html file 
<ion-nav-view>
    <div ng-show="loadder" class="loddingSvg">
        <div class="svgImage"></div>
    </div>
</ion-nav-view>

// css file

.loddingSvg {
    height: 100%;
    background-color: rgba(0, 0, 0, 0.1);
    position: absolute;
    z-index: 99;
    left: 0;
    right: 0;
}

.svgImage {
    background: url(../img/default.svg) no-repeat;
    position: relative;
    z-index: 99;
    height: 65px;
    width: 65px;
    background-size: 56px;
    top: 50%;
    margin: 0 auto;
}

// edit app.js

 .run(function($ionicPush, $rootScope, $ionicPlatform) {




        $rootScope.$on('$stateChangeStart',
            function(event, toState, toParams, fromState, fromParams) {
                $rootScope.loadder = true;
            });

        $rootScope.$on('$stateChangeSuccess',
            function(event, toState, toParams, fromState, fromParams) {
                $rootScope.loadder = false;
            });

});

0

यदि कोई उपयोग कर रहा है ngRoute, resolveतो अगले दृश्य को लोड करने से पहले प्रतीक्षा कर रहा है , और angular-bootstrap-uiयूआई का उपयोग कर रहा है, तो आप निम्न कार्य कर सकते हैं :

app.config([
  "$routeProvider", "$locationProvider", function($routeProvider, $locationProvider) {
    return $routeProvider.when("/seasons/:seasonId", {
      templateUrl: "season-manage.html",
      controller: "SeasonManageController",
      resolve: {
        season: [
          "$route", "$q", "$http", "$modal", function($route, $q, $http, $modal) {
            var modal, promise, seasonId;
            modal = $modal.open({
              backdrop: "static",
              template: "<div>\n  <div class=\"modal-header\">\n    <h3 class=\"modal-title\">\n      Loading...\n    </h3>\n  </div>\n  <div class=\"modal-body\">\n    <progressbar\n      class=\"progress-striped active\"\n      value=\"'100'\">\n    </progressbar>\n  </div>\n</div>",
              keyboard: false,
              size: "lg"
            });
            promise = $q.defer();
            seasonId = $route.current.params.seasonId;
            $http.get("/api/match/seasons/" + seasonId).success(function(data) {
              modal.close();
              promise.resolve(data);
            }).error(function(data) {
              modal.close();
              promise.reject(data);
            });

            return promise.promise;
          }
        ]
      }
    });
  }
]);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.