235 votes

Afficher le GIF d'un spinner pendant une requête $http en AngularJS ?

J'utilise le $http d'AngularJS pour effectuer une requête Ajax.

Comment afficher un GIF de type "spinner" (ou un autre type d'indicateur d'activité) pendant l'exécution de la requête Ajax ?

Je ne vois rien qui ressemble à un ajaxstartevent dans la documentation d'AngularJS.

2 votes

Si vous voulez un simple spinner basé sur les HTTP Interceptors, j'ai un module angulaire pour cela. Il utilise le populaire Identified Sham spinner. Jetez-y un coup d'oeil : github.com/harinair/angular-sham-spinner

1 votes

J'ai écrit un plugin angular-httpshooter il libère un événement avec les données de configuration juste avant le déclenchement de l'appel et en libère un autre juste après la réception de la réponse, vous pouvez écrire des chargeurs globaux qui capturent ces événements.

472voto

Josh David Miller Points 66508

Cela dépend vraiment de votre cas d'utilisation spécifique, mais un moyen simple serait de suivre un modèle comme celui-ci :

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

Puis réagissez-y dans votre modèle :

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

225 votes

Si vous avez plusieurs requêtes ajax en même temps, vous pouvez déclarer loading comme un nombre entier $scope.loading = 0; Quand une demande commence, vous faites $scope.loading++; et quand ça se termine, vous faites $scope.loading--; . Et il n'y a rien à changer dans le modèle. Le spinner est donc affiché lorsqu'il y a au moins une demande en cours, et est caché le reste du temps.

16 votes

Vous devriez probablement définir le chargement à false dans la fonction de repli d'erreur également.

3 votes

@sebnukem Vous avez raison. C'était un exemple de haut niveau, mais je l'ai quand même ajouté pour plus de clarté. Merci pour vos commentaires !

88voto

bulltorious Points 2664

Voici les actuel les anciennes incantations d'AngularJS :

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']).
//.......

Voici le reste (HTML / CSS)....using

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

pour l'activer. NOTE : ce qui précède est utilisé dans le module angulaire au début de l'article.

#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 votes

Notez que vous pouvez utiliser angular.element('#mydiv').show() au lieu de $('#mydiv').show()

8 votes

Cela ne fonctionne pas si votre page fait plusieurs requêtes ajax. Il cachera le gif de chargement après la fin de la première requête.

38 votes

Selon les meilleures pratiques d'AngularJS (que la solution acceptée enfreint), vous ne devriez pas modifier le DOM en dehors d'une directive. Envisagez d'invoquer show/hide sur des éléments à partir d'une directive.

31voto

Si vous utilisez ngResource, l'attribut $resolved d'un objet est utile pour les chargeurs :

Pour une ressource comme suit :

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

Vous pouvez lier un chargeur à l'attribut $resolved de l'objet ressource :

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

14voto

eddiec Points 2467

https://github.com/wongatech/angular-http-loader est un bon projet pour cela.

Exemple ici http://wongatech.github.io/angular-http-loader/

Le code ci-dessous montre un modèle exemple/loader.tpl.html lorsqu'une requête se produit.

<div ng-http-loader template="example/loader.tpl.html"></div>

13voto

Aperçu Points 5245

Je viens de découvrir le angular-busy qui montre un petit chargeur dépendant d'un appel asynchrone.

Par exemple, si vous devez faire un GET , faites référence à la promesse dans votre $scope ,

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

et l'appeler ainsi :

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

Voici le <a href="https://github.com/cgross/angular-busy" rel="nofollow noreferrer"><strong>GitHub</strong></a> .

Vous pouvez également l'installer en utilisant bower (n'oubliez pas de mettre à jour les dépendances de votre projet) :

bower install angular-busy --save

0 votes

Je n'ai pas trouvé comment "désactiver un élément" dans la documentation. Pouvez-vous m'expliquer comment ? Par exemple, je veux désactiver un bouton pendant que le spinner est affiché.

0 votes

angulaire-busy seulement mettre sur votre élément un masque, je ne pense pas que vous pouvez désactiver un bouton comme vous voulez le faire, mais vous pouvez mettre le fond sur lui avec un modèle vide pour donner cette impression. Je ne suis pas un locuteur natif, désolé pour la confusion :)

0 votes

Ok, j'ai modifié votre réponse pour éviter que quelqu'un d'autre ait la même confusion. Un français parlant anglais à un autre français est toujours déroutant :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X