AngularJS'de $ http isteği sırasında spinner GIF gösterilsin mi?


234

$httpBir Ajax isteği yapmak için AngularJS hizmetini kullanıyorum .

Ajax isteği yürütülürken dönen bir GIF (veya başka bir meşgul göstergesi türü) nasıl gösterilebilir?

ajaxstarteventAngularJS belgelerinde böyle bir şey görmüyorum .


2
HTTP Durdurucularına dayalı basit bir döndürücü istiyorsanız, bunun için açısal bir modülüm var. Popüler Identified Sham spinner'ı kullanır. Bir göz atın: github.com/harinair/angular-sham-spinner
Hari Gangadharan

1
Bir eklenti açısal-httpshooter yazdım , çağrı çekiminden hemen önce yapılandırma verileri içeren bir olay yayınladı ve resposne aldıktan hemen sonra başka bir tane yayınladı, bu olayları yakalayan küresel yükleyiciler yazabilirsiniz
Siddharth

Yanıtlar:


88

Şu anki geçmiş AngularJS büyülerinden bazıları :

angular.module('SharedServices', [])
    .config(function ($httpProvider) {
        $httpProvider.responseInterceptors.push('myHttpInterceptor');
        var spinnerFunction = function (data, headersGetter) {
            // todo start the spinner here
            //alert('start spinner');
            $('#mydiv').show();
            return data;
        };
        $httpProvider.defaults.transformRequest.push(spinnerFunction);
    })
// register the interceptor as a service, intercepts ALL angular ajax http calls
    .factory('myHttpInterceptor', function ($q, $window) {
        return function (promise) {
            return promise.then(function (response) {
                // do something on success
                // todo hide the spinner
                //alert('stop spinner');
                $('#mydiv').hide();
                return response;

            }, function (response) {
                // do something on error
                // todo hide the spinner
                //alert('stop spinner');
                $('#mydiv').hide();
                return $q.reject(response);
            });
        };
    });

//regular angular initialization continued below....
angular.module('myApp', [ 'myApp.directives', 'SharedServices']).
//.......

İşte geri kalanı (HTML / CSS) .... kullanarak

$('#mydiv').show(); 
$('#mydiv').hide(); 

değiştirmek için. NOT: yukarıdaki direk başında köşeli modülünde kullanılır

#mydiv {  
    position:absolute;
    top:0;
    left:0;
    width:100%;
    height:100%;
    z-index:1000;
    background-color:grey;
    opacity: .8;
 }

.ajax-loader {
    position: absolute;
    left: 50%;
    top: 50%;
    margin-left: -32px; /* -1 * image width / 2 */
    margin-top: -32px;  /* -1 * image height / 2 */
    display: block;     
}

<div id="mydiv">
    <img src="lib/jQuery/images/ajax-loader.gif" class="ajax-loader"/>
</div>

19
Not kendinizin kullanabileceği angular.element('#mydiv').show()yerine$('#mydiv').show()
JMaylin

8
sayfanız birden fazla ajax isteği yaparsa bu çalışmaz. İlk istekler bittikten sonra yükleme gif'ini gizler.
Meeker

38
AngularJS'nin (kabul edilen çözümün ihlal ettiği) en iyi uygulamalarına göre, bir yönerge dışında DOM'u değiştirmemelisiniz. Bir yönerge içerisindeki elemanlar üzerinde gösteri / gizleme yapmayı düşünün.
Mariusz

7
Yorum yapmak için yeterli bildiğimden emin değilim ... Ama bunu yapmak için doğru yolu ng-classöğeleri göstermek ve gizlemek için JQuery kullanmak yerine yönergeyi kullanmak olmaz mı?
James Heald

2
@JamesHeald doğrudur .. Angular'da herhangi bir dom manipülasyonu için gerçekten jQuery kullanmanız gerekmez. Şuna bakın: ng-class, ng-if, ng-hide, ng-show, vb. İhtiyacınız olan hemen hemen her şey için bir direktif var.
jKlaus

471

Bu gerçekten sizin özel kullanım durumunuza bağlıdır, ancak basit bir yol aşağıdaki gibi bir deseni izler:

.controller('MainCtrl', function ( $scope, myService ) {
  $scope.loading = true;
  myService.get().then( function ( response ) {
    $scope.items = response.data;
  }, function ( response ) {
    // TODO: handle the error somehow
  }).finally(function() {
    // called no matter success or failure
    $scope.loading = false;
  });
});

Ardından şablonunuzda buna tepki verin:

<div class="spinner" ng-show="loading"></div>
<div ng-repeat="item in items>{{item.name}}</div>

223
Aynı anda birden çok ajax isteğiniz varsa, bir istek başladığında ve sona erdiğinde loadingbir tamsayı olarak bildirebilirsiniz . Ve şablonda değiştirilecek hiçbir şey yok. Dolayısıyla, en az bir istek devam $scope.loading = 0;$scope.loading++;$scope.loading--;
ettiğinde dönücü görüntülenir

16
Hata yedek işlevinde de yüklemeyi false olarak ayarlamanız gerekir.
sebnukem

3
@sebnukem Haklısın. Bu oldukça üst düzey bir örnekti, ama devam ettim ve netlik için yine de ekledim. Geri dönüşünüz için teşekkür ederiz!
Josh David Miller

1
@JMaylin - Daha sonra $ scope'da $ watch kullanabilirsiniz. Loading başka şeyler yapmak
Jason

5
Daha da iyi bir yol, $scope.loading = falsehem başarı hem de başarısız geri arama koymak yerine, koymaktır .finally(). Şöyle görünecektir:mySvc.get().then(success, fail).finally(function() { $scope.loading = false; });
Tom

44

İşte kullanarak bir sürümüdür directiveve ng-hide.

Bu, açısal servisi üzerinden yapılan tüm çağrılar sırasında yükleyiciyi gösterecektir $http.

Şablonda:

<div class="loader" data-loading></div>

direktif:

angular.module('app')
  .directive('loading', ['$http', function ($http) {
    return {
      restrict: 'A',
      link: function (scope, element, attrs) {
        scope.isLoading = function () {
          return $http.pendingRequests.length > 0;
        };
        scope.$watch(scope.isLoading, function (value) {
          if (value) {
            element.removeClass('ng-hide');
          } else {
            element.addClass('ng-hide');
          }
        });
      }
    };
}]);

ng-hideöğeyi sınıfta kullanarak jquery'den kaçınabilirsiniz.


Özelleştir: interceptor

Bir yükleme durdurucu oluşturursanız, yükleyiciyi bir koşula bağlı olarak gösterebilir / gizleyebilirsiniz.

direktif:

var loadingDirective = function ($rootScope) {
  return function ($scope, element, attrs) {
      $scope.$on("loader_show", function () {
          return element.removeClass('ng-hide');
      });
      return $scope.$on("loader_hide", function () {
          return element.addClass('ng-hide');
      });
  };
};

önleme:

  • örneğin: göstermezler spinnerzamanresponse.background === true;
  • Kesişim requestve / veya responseayarlamak $rootScope.$broadcast("loader_show");veya$rootScope.$broadcast("loader_hide");

önleme yazma hakkında daha fazla bilgi


@punkrockpolly Belirli senaryomda, bir hizmeti çağıran iki ayrı bileşene sahibim. Ama bu sadece bunlardan biri için çalışıyor, Bunu yeniden kullanılabilir hale getirmek için bir parametre veya bir şey geçmeli miyim?
RicardoGonzales

@razorblade $http, herhangi bir hizmette bir çağrı yaptığınızda dönecektir .
punkrockpolly

31

NgResource kullanıyorsanız, bir nesnenin $ resolved özelliği yükleyiciler için kullanışlıdır:

Aşağıdaki gibi bir kaynak için:

var User = $resource('/user/:id', {id:'@id'});
var user = User.get({id: 1})

Bir yükleyiciyi kaynak nesnesinin $ resolved özniteliğine bağlayabilirsiniz:

<div ng-hide="user.$resolved">Loading ...</div>


13

Sadece angular-busybazı asenkron çağrılara bağlı olarak küçük bir yükleyici gösteren yönergeyi keşfettim .

Örneğin, bir a yapmanız GETgerekiyorsa $scope,

$scope.req = $http.get('http://google.fr');

ve şöyle deyin:

<div cg-busy="req"></div>

İşte GitHub.

Bunu kullanarak da yükleyebilirsiniz bower(proje bağımlılıklarınızı güncellemeyi unutmayın):

bower install angular-busy --save

Belgelerde "bazı öğelerin nasıl devre dışı bırakılacağını" bulamadım. Nasıl olduğunu açıklayabilir misin? Örneğin, değer değiştirici gösterilirken bir düğmeyi devre dışı bırakmak istiyorum.
c4k

açısal-meşgul sadece elemanınıza bir maske koymak, bir düğmeyi istediğiniz gibi devre dışı bırakabileceğinizi düşünmüyorum, ancak bu izlenimi vermek için üzerindeki arka planı boş bir şablonla ayarlayabilirsiniz. Ben anadili değilim, karışıklık için özür dilerim :)
Balthazar

Tamam, başka birinin aynı karışıklığa sahip olmasını önlemek için cevabınızı düzenledim. Fransızca başka bir Fransızca konuşan İngilizce her zaman kafa karıştırıcı :)
c4k

5

Api çağrılarınızı bir servis / fabrika içinde sarıyorsanız , o zaman yükleme sayacını takip edebilirsiniz ( cevap başına ve @JMaylin tarafından mükemmel eşzamanlı öneri) ve yükleme sayacına bir yönerge ile başvurabilirsiniz. Veya bunların herhangi bir kombinasyonu.

API WRAPPER

yourModule
    .factory('yourApi', ['$http', function ($http) {
        var api = {}

        //#region ------------ spinner -------------

        // ajax loading counter
        api._loading = 0;

        /**
         * Toggle check
         */
        api.isOn = function () { return api._loading > 0; }

        /**
         * Based on a configuration setting to ignore the loading spinner, update the loading counter
         * (for multiple ajax calls at one time)
         */
        api.spinner = function(delta, config) {
            // if we haven't been told to ignore the spinner, change the loading counter
            // so we can show/hide the spinner

            if (NG.isUndefined(config.spin) || config.spin) api._loading += delta;

            // don't let runaway triggers break stuff...
            if (api._loading < 0) api._loading = 0;

            console.log('spinner:', api._loading, delta);
        }
        /**
         * Track an ajax load begin, if not specifically disallowed by request configuration
         */
        api.loadBegin = function(config) {
            api.spinner(1, config);
        }
        /**
         * Track an ajax load end, if not specifically disallowed by request configuration
         */
        api.loadEnd = function (config) {
            api.spinner(-1, config);
        }

        //#endregion ------------ spinner -------------

        var baseConfig = {
            method: 'post'
            // don't need to declare `spin` here
        }

        /**
         * $http wrapper to standardize all api calls
         * @param args stuff sent to request
         * @param config $http configuration, such as url, methods, etc
         */
        var callWrapper = function(args, config) {
            var p = angular.extend(baseConfig, config); // override defaults

            // fix for 'get' vs 'post' param attachment
            if (!angular.isUndefined(args)) p[p.method == 'get' ? 'params' : 'data'] = args;

            // trigger the spinner
            api.loadBegin(p);

            // make the call, and turn of the spinner on completion
            // note: may want to use `then`/`catch` instead since `finally` has delayed completion if down-chain returns more promises
            return $http(p)['finally'](function(response) {
                api.loadEnd(response.config);
                return response;
            });
        }

        api.DoSomething = function(args) {
            // yes spinner
            return callWrapper(args, { cache: true });
        }
        api.DoSomethingInBackground = function(args) {
            // no spinner
            return callWrapper(args, { cache: true, spin: false });
        }

        // expose
        return api;
    });

SPİNNER DİREKTİFİ

(function (NG) {
    var loaderTemplate = '<div class="ui active dimmer" data-ng-show="hasSpinner()"><div class="ui large loader"></div></div>';

    /**
     * Show/Hide spinner with ajax
     */
    function spinnerDirective($compile, api) {
        return {
            restrict: 'EA',
            link: function (scope, element) {
                // listen for api trigger
                scope.hasSpinner = api.isOn;

                // attach spinner html
                var spin = NG.element(loaderTemplate);
                $compile(spin)(scope); // bind+parse
                element.append(spin);
            }
        }
    }

    NG.module('yourModule')
        .directive('yourApiSpinner', ['$compile', 'yourApi', spinnerDirective]);
})(angular);

KULLANIM

<div ng-controller="myCtrl" your-api-spinner> ... </div>

5

Sayfa yüklemeleri ve modülleri için, en kolay yol ng-showyönergeyi kullanmak ve kapsam veri değişkenlerinden birini kullanmaktır. Gibi bir şey:

ng-show="angular.isUndefined(scope.data.someObject)".

Burada, someObjecttanımlanmamışken, iplikçi gösterecektir. Hizmet verilerle döndüğünde ve someObjectdoldurulduktan sonra, döndürücü gizli durumuna geri döner.


3

Bu sanırım bir spinner eklemek için en kolay yolu: -

Ng-show'u bu güzel iplikçilerin herhangi birinin div etiketi ile kullanabilirsiniz http://tobiasahlin.com/spinkit/ {{Bu benim sayfam değil}}

ve sonra bu tür bir mantığı kullanabilirsiniz

//ajax start
    $scope.finderloader=true;
    
          $http({
    method :"POST",
    url : "your URL",
  data: { //your data
     
     }
  }).then(function mySucces(response) {
    $scope.finderloader=false;
      $scope.search=false;          
    $scope.myData =response.data.records;
  });
     
    //ajax end 
    
<div ng-show="finderloader" class=spinner></div>
//add this in your HTML at right place


3
Based on Josh David Miller response:

  <body>
  <header>
  </header>
<div class="spinner" ng-show="loading">
  <div class="loader" ></div>
</div>

<div ng-view=""></div>

<footer>
</footer>

</body>

Bu css'i ekle:

    .loader {
  border: 16px solid #f3f3f3;
  border-radius: 50%;
  border-top: 16px solid #3498db;
  border-bottom : 16px solid black;
  width: 80px;
  height: 80px;
  -webkit-animation: spin 2s linear infinite;
  animation: spin 2s linear infinite;
  position: absolute;
  top: 45%;
  left: 45%;
}

@-webkit-keyframes spin {
  0% { -webkit-transform: rotate(0deg); }
  100% { -webkit-transform: rotate(360deg); }
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}


.spinner{
  width: 100%;
height: 100%;
z-index: 10000;
position: absolute;
top: 0;
left: 0;
margin: 0 auto;
text-align: center;
vertical-align: middle;
background: white;
opacity: 0.6;
}

Ve sadece açısal eklemenizde:

$ rootScope.loading = yanlış; $ rootScope.loading = true; -> $ http.get sona erdiğinde.


2

@Bulltorious'dan gelen büyük yanıtın versiyonunu paylaşıyorum, daha yeni açısal yapılar için güncellendi (bu kodla 1.5.8 sürümünü kullandım) ve ayrıca @ JMaylin'in birden fazla eşzamanlı talebe karşı sağlam olması için bir sayaç kullanma fikrini dahil etti ve minimum milisaniyeden az süren istekler için animasyonu göstermeyi atlama seçeneği:

var app = angular.module('myApp');
var BUSY_DELAY = 1000; // Will not show loading graphic until 1000ms have passed and we are still waiting for responses.

app.config(function ($httpProvider) {
  $httpProvider.interceptors.push('busyHttpInterceptor');
})
  .factory('busyHttpInterceptor', ['$q', '$timeout', function ($q, $timeout) {
    var counter = 0;
    return {
      request: function (config) {
        counter += 1;
        $timeout(
          function () {
            if (counter !== 0) {
              angular.element('#busy-overlay').show();
            }
          },
          BUSY_DELAY);
        return config;
      },
      response: function (response) {
        counter -= 1;
        if (counter === 0) {
          angular.element('#busy-overlay').hide();
        }
        return response;
      },
      requestError: function (rejection) {
        counter -= 1;
        if (counter === 0) {
          angular.element('#busy-overlay').hide();
        }
        return rejection;
      },
      responseError: function (rejection) {
        counter -= 1;
        if (counter === 0) {
          angular.element('#busy-overlay').hide();
        }
        return rejection;
      }
    }
  }]);

2

Http istek çağrılarını yönetmek için açısal önleme aracını kullanabilirsiniz

  <div class="loader">
    <div id="loader"></div>
  </div>

<script>
    var app = angular.module("myApp", []);

    app.factory('httpRequestInterceptor', ['$rootScope', '$location', function ($rootScope, $location) {
        return {
            request: function ($config) {
                $('.loader').show();
                return $config;
            },
            response: function ($config) {
                $('.loader').hide();
                return $config;
            },
            responseError: function (response) {
                return response;
            }
        };
    }]);

    app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider',
        function ($stateProvider, $urlRouterProvider, $httpProvider) {
            $httpProvider.interceptors.push('httpRequestInterceptor');
        }]);

</script>

https://stackoverflow.com/a/49632155/4976786


2

Durdurucular veya jQuery olmadan basit yol

Bu, üçüncü taraf bir kütüphane, kesiciler veya jQuery gerektirmeyen bir döndürücüyü göstermenin basit bir yoludur.

Denetleyicide bir bayrak ayarlayın ve sıfırlayın.

function starting() {
    //ADD SPINNER
    vm.starting = true;
    $http.get(url)
      .then(function onSuccess(response) {
        vm.data = response.data;
    }).catch(function onReject(errorResponse) {
        console.log(errorResponse.status);
    }).finally(function() {
        //REMOVE SPINNER
        vm.starting = false;
    });
};

HTML'de bayrağı kullanın:

<div ng-show="vm.starting">
    <img ng-src="spinnerURL" />
</div>

<div ng-hide="vm.starting">
    <p>{{vm.data}}</p>
</div>

vm.startingİşareti ayarlanır trueXHR başlar ve ne zaman XHR tamamlanana temizlenir zaman.


1

Bu benim için iyi çalışıyor:

HTML:

  <div id="loader" class="ng-hide" ng-show="req.$$state.pending">
    <img class="ajax-loader" 
         width="200" 
         height="200" 
         src="/images/spinner.gif" />
  </div>

Açısal:

  $scope.req = $http.get("/admin/view/"+id).success(function(data) {          
      $scope.data = data;
  });

$ Http'den iade edilen söz beklemede iken, ng-show bunu "doğru" olarak değerlendirecektir. Söz verildiğinde bu otomatik olarak güncellenir ... tam olarak istediğimiz şey budur.


Bunu yapmanın dinamik yolu bu değil.
Umair Hamid

Bunun neden bu hedefe ulaşmak için dinamik bir yol olmadığını düşündüğünüzü açıklar mısınız? Bu, bu yayını okuyan diğerlerinin öğrenmesine yardımcı olacaktır. Teşekkür ederim.
nemli

Başvurumda birden fazla isteğim var. $ scope.req yalnızca tek bir istek için çalışır. Bu özel istek tam yükleyici gizlendiğinde ve diğer istekleri tamamlamayı beklemediğinde. Bunu başarmanın en iyi yolu önleyicileri kullanmaktır.
Umair Hamid

1

Http isteğinde yükleme çubuğunu göstermek için aşağıdaki önleme kullanılır

'use strict';
appServices.factory('authInterceptorService', ['$q', '$location', 'localStorage','$injector','$timeout', function ($q, $location, localStorage, $injector,$timeout) {

var authInterceptorServiceFactory = {};
var requestInitiated;

//start loading bar
var _startLoading = function () {
   console.log("error start loading");
   $injector.get("$ionicLoading").show();

}

//stop loading bar
var _stopLoading = function () {
    $injector.get("$ionicLoading").hide();
}

//request initiated
var _request = function (config) {
     requestInitiated = true;
    _startLoading();
    config.headers = config.headers || {};
    var authDataInitial = localStorage.get('authorizationData');
    if (authDataInitial && authDataInitial.length > 2) {
        var authData = JSON.parse(authDataInitial);
        if (authData) {
            config.headers.Authorization = 'Bearer ' + authData.token;
        }
    }
    return config;
}

//request responce error
var _responseError = function (rejection) {
   _stopLoading();
    if (rejection.status === 401) {
        $location.path('/login');
    }
    return $q.reject(rejection);
}

//request error
var _requestError = function (err) {
   _stopLoading();
   console.log('Request Error logging via interceptor');
   return err;
}

//request responce
var _response = function(response) {
    requestInitiated = false;

   // Show delay of 300ms so the popup will not appear for multiple http request
   $timeout(function() {

        if(requestInitiated) return;
        _stopLoading();
        console.log('Response received with interceptor');

    },300);

return response;
}



authInterceptorServiceFactory.request = _request;
authInterceptorServiceFactory.responseError = _responseError;
authInterceptorServiceFactory.requestError = _requestError;
authInterceptorServiceFactory.response = _response;

return authInterceptorServiceFactory;
}]);

0
.factory('authHttpResponseInterceptor', ['$q', function ($q) {
        return {
            request: function(config) {
                angular.element('#spinner').show();
                return config;
            },
            response : function(response) {
                angular.element('#spinner').fadeOut(3000);
                return response || $q.when(response);
            },
            responseError: function(reason) {
                angular.element('#spinner').fadeOut(3000);
                return $q.reject(reason);
            }
        };
    }]);



 .config(['$routeProvider', '$locationProvider', '$translateProvider', '$httpProvider',
            function ($routeProvider, $locationProvider, $translateProvider, $httpProvider) {
                $httpProvider.interceptors.push('authHttpResponseInterceptor');
    }
]);

in your Template
<div id="spinner"></div>


css   

#spinner,
#spinner:after {
  border-radius: 50%;
  width: 10em;
  height: 10em;
  background-color: #A9A9A9;
  z-index: 10000;
  position: absolute;
  left: 50%;
  bottom: 100px;
}
@-webkit-keyframes load8 {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
@keyframes load8 {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}

1
Yalnızca kod yanıtları pek kullanışlı değildir.
Phantômaxx

0

bu kodla direktif oluştur:

$scope.$watch($http.pendingRequests, toggleLoader);

function toggleLoader(status){
  if(status.length){
    element.addClass('active');
  } else {
    element.removeClass('active');
  }
}

0

Farklı url değişiklikleri arasındaki yüklemeyi göstermek için başka bir çözüm:

$rootScope.$on('$locationChangeStart', function() {
  $scope.loading++;
});

$rootScope.$on('$locationChangeSuccess', function() {
  $timeout(function() {
    $scope.loading--;
  }, 300);
});

Ve sonra biçimlendirmede sadece iplikçiyi ile değiştirin ng-show="loading".

Ajax isteklerinde görüntülemek istiyorsanız $scope.loading++, istek başladığında ve bittiğinde ekleyin $scope.loading--.


0

Bunun gibi bir şey de deneyebilirsiniz:

Direktif oluştur:

myApp.directive('loader', function () {
    return {
        restrict: 'A',
        scope: {cond: '=loader'},
        template: '<span ng-if="isLoading()" class="soft"><span class="fa fa-refresh fa-spin"></span></span>',
        link: function (scope) {
            scope.isLoading = function() {
                var ret = scope.cond === true || (
                        scope.cond &&
                        scope.cond.$$state &&
                        angular.isDefined(scope.cond.$$state.status) &&
                        scope.cond.$$state.status === 0
                    );
                return ret;
            }
        }
    };
}); 

Sonra mainCtrl'e böyle bir şey eklersiniz

    // Return TRUE if some request is LOADING, else return FALSE
    $scope.isLoading = function() {
        return $http.pendingRequests.length > 0;
    };

Ve HTML şöyle görünebilir:

<div class="buttons loader">
    <span class="icon" loader="isLoading()"></span>
</div>

0

Aşağıdaki şekilde tüm istekler not edilecek ve yalnızca tüm istekler yapıldıktan sonra gizlenecektir:

app.factory('httpRequestInterceptor', function(LoadingService, requestCount) {
    return {
        request: function(config) {
            if (!config.headers.disableLoading) {
                requestCount.increase();
                LoadingService.show();
            }
            return config;
        }
    };
}).factory('httpResponseInterceptor', function(LoadingService, $timeout, error, $q, requestCount) {
    function waitAndHide() {
        $timeout(function() {
            if (requestCount.get() === 0){
                LoadingService.hide();
            }
            else{
                waitAndHide();
            }
        }, 300);
    }

    return {
        response: function(config) {
            requestCount.descrease();
            if (requestCount.get() === 0) {
                waitAndHide();
            }
            return config;
        },
        responseError: function(config) {
            requestCount.descrease();
            if (requestCount.get() === 0) {
                waitAndHide();
            }
            var deferred = $q.defer();
            error.show(config.data, function() {
                deferred.reject(config);
            });
            return deferred.promise;
        }
    };
}).factory('requestCount', function() {
    var count = 0;
    return {
        increase: function() {
            count++;
        },
        descrease: function() {
            if (count === 0) return;
            count--;
        },
        get: function() {
            return count;
        }
    };
})


0

Konumun işlevselliği : sabit son zamanlarda değiştiğinden, gif yükleyiciyi tüm öğelerin üstünde göstermekte zorlandım, bu yüzden açısal dahili jQuery kullanmak zorunda kaldım .

Html

<div ng-controller="FetchController">
      <div id="spinner"></div>
</div>

css

#spinner {display: none}
body.spinnerOn #spinner { /* body tag not necessary actually */
   display: block;
   height: 100%;
   width: 100%;
   background: rgba(207, 13, 48, 0.72) url(img/loader.gif) center center no-repeat;
   position: fixed;
   top: 0;
   left: 0;
   z-index: 9999;
}
body.spinnerOn main.content { position: static;} /* and whatever content needs to be moved below your fixed loader div */

kontrolör

app.controller('FetchController', ['$scope', '$http', '$templateCache', '$location', '$q',
function($scope, $http, $templateCache, $location, $q) {

angular.element('body').addClass('spinnerOn'); // add Class to body to show spinner

$http.post( // or .get(
    // your data here
})
.then(function (response) {
    console.info('success');     
    angular.element('body').removeClass('spinnerOn'); // hide spinner

    return response.data;               
}, function (response) {                   
    console.info('error'); 
    angular.element('body').removeClass('spinnerOn'); // hide spinner
});

})

Bu yardımcı olur umarım :)


0

Tüm cevaplar karmaşık veya karmaşıktır ya da KURU konseptini bildiğimizde çok yanlış bir uygulama olan her istek üzerine bazı değişkenler ayarlamanız gerekir. Burada basit önleme örneği, ajax başladığında fareyi beklemeye ayarladım ve ajax bittiğinde otomatik olarak ayarladım.

$httpProvider.interceptors.push(function($document) {
    return {
     'request': function(config) {
         // here ajax start
         // here we can for example add some class or show somethin
         $document.find("body").css("cursor","wait");

         return config;
      },

      'response': function(response) {
         // here ajax ends
         //here we should remove classes added on request start

         $document.find("body").css("cursor","auto");

         return response;
      }
    };
  });

Kod, uygulama yapılandırmasına eklenmelidir app.config. Yükleme durumunda farenin nasıl değiştirileceğini gösterdim ancak orada herhangi bir yükleyici içeriğini göstermek / gizlemek veya yükleyiciyi gösteren bazı css sınıflarını eklemek mümkündür.

Durdurucu her ajax çağrısında çalışır, bu nedenle her http çağrısında özel boole değişkenleri ($ scope.loading = true / false vb.) Oluşturmanıza gerek yoktur .


0

İşte benim uygulama, bir ng-show ve bir istek sayacı kadar basit.

Tüm http $ talepleri için yeni bir hizmet kullanır:

myApp.service('RqstSrv', [ '$http', '$rootScope', function($http, $rootScope) {
    var rqstService = {};

    rqstService.call = function(conf) {

        $rootScope.currentCalls = !isNaN($rootScope.currentCalls) ?  $rootScope.currentCalls++ : 0;

        $http(conf).then(function APICallSucceed(response) {
            // Handle success
        }, function APICallError(response) {
            // Handle error
        }).then(function() {
            $rootScope.currentCalls--;
        });
    }
} ]);

Ardından yükleyici tabanınızı mevcut çağrıların sayısına göre kullanabilirsiniz:

<img data-ng-show="currentCalls > 0" src="images/ajax-loader.gif"/>

0

her http istek çağrısı için yükleyici göstermek istiyorsanız, http istek çağrılarını yönetmek için açısal önleme aracını kullanabilirsiniz,

işte örnek bir kod

<body data-ng-app="myApp">
<div class="loader">
    <div id="loader"></div>
</div>

<script>
    var app = angular.module("myApp", []);

    app.factory('httpRequestInterceptor', ['$rootScope', '$location', function ($rootScope, $location) {
        return {
            request: function ($config) {
                $('.loader').show();
                return $config;
            },
            response: function ($config) {
                $('.loader').hide();
                return $config;
            },
            responseError: function (response) {
                return response;
            }
        };
    }]);

    app.config(['$stateProvider', '$urlRouterProvider', '$httpProvider',
        function ($stateProvider, $urlRouterProvider, $httpProvider) {
            $httpProvider.interceptors.push('httpRequestInterceptor');
        }]);

</script>
</body>

0

Sadece ng-show ve bir boolean kullanın

Direktif kullanmaya gerek yok, karmaşık olmaya gerek yok.

Gönder düğmesinin yanına veya döndürücünün olmasını istediğiniz yere koyacağınız kod:

<span ng-show="dataIsLoading">
  <img src="http://www.nasa.gov/multimedia/videogallery/ajax-loader.gif" style="height:20px;"/>
</span>

Ve sonra kumandanızda:

$scope.dataIsLoading = true

let url = '/whatever_Your_URL_Is'
$http.get(url)
.then(function(response) {
  $scope.dataIsLoading = false
})

-1

İşte hissediyorum diğer çözüm burada yayınlanan çok daha kolay olduğunu hissediyorum. Ne kadar "güzel" olduğundan emin değilim, ama tüm sorunlarımı çözdü

"Loading" adında bir css stilim var

.loading { display: none; }

Yükleme div için html ne olursa olsun olabilir ama bazı FontAwesome simgeleri ve orada spin yöntemi kullanılır:

<div style="text-align:center" ng-class="{ 'loading': !loading }">
    <br />
    <h1><i class="fa fa-refresh fa-spin"></i> Loading data</h1>
</div>

Gizlemek istediğiniz öğelerde sadece şunu yazın:

<something ng-class="{ 'loading': loading }" class="loading"></something>

ve fonksiyonda bunu sadece yüke ayarladım.

(function (angular) {
    function MainController($scope) {
        $scope.loading = true

SignalPro kullanıyorum yani hubProxy.client.allLocks işlevinde (onun bittiğinde kilitleri geçiyor) ben koymak juts

 $scope.loading = false
 $scope.$apply();

Bu, yükleme sınıfını yükte ayarladığım ve AngularJS daha sonra kaldırdığı için sayfa yüklenirken {{someField}} öğesini de gizler.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.