235

$httpAngularJSのサービスを使用してAjax リクエストを作成しています。

Ajax リクエストの実行中にスピナー GIF (または別の種類のビジー インジケーター) を表示するにはどうすればよいですか?

ajaxstarteventAngularJS のドキュメントに のようなものはありません。

4

27 に答える 27

472

これは特定のユースケースに大きく依存しますが、簡単な方法は次のようなパターンに従います。

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

そして、テンプレートでそれに反応します:

<div class="spinner" ng-show="loading"></div>
<div ng-repeat="item in items>{{item.name}}</div>
于 2013-02-22T21:18:27.497 に答える
44

directiveとを使用したバージョンを次に示しng-hideます。

これにより、Angular のサービスを介したすべての呼び出し中にローダーが表示されます。$http

テンプレートでは:

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

指令:

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ことで、jquery を回避できます。


カスタマイズ: を追加interceptor

ローディングインターセプターを作成すると、条件に基づいてローダーを表示/非表示にすることができます。

指令:

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

インターセプター:

  • spinner例: 次の場合は表示しないresponse.background === true;
  • インターセプトrequestおよび/またはresponse設定$rootScope.$broadcast("loader_show");または$rootScope.$broadcast("loader_hide");

インターセプターの作成に関する詳細情報

于 2015-08-12T02:02:47.277 に答える
31

ngResource を使用している場合、オブジェクトの $resolved 属性はローダーに役立ちます。

次のようなリソースの場合:

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

ローダーをリソース オブジェクトの $resolved 属性にリンクできます。

<div ng-hide="user.$resolved">Loading ...</div>
于 2014-09-16T16:18:38.500 に答える
3

これは、私が推測するスピナーを追加する最も簡単な方法です:-

これらの美しいスピナーのいずれかの div タグで ng-show を使用できます http://tobiasahlin.com/spinkit/ {{これは私のページではありません}}

そして、この種のロジックを使用できます

//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

于 2016-07-09T16:45:30.970 に答える
2

インターセプターや jQuery を使用しない簡単な方法

これは、サードパーティのライブラリ、インターセプター、または jQuery を必要としないスピナーを表示する簡単な方法です。

コントローラーで、フラグを設定およびリセットします。

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 では、次のフラグを使用します。

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

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

このvm.startingフラグはtrue、XHR の開始時に設定され、XHR の完了時にクリアされます。

于 2018-07-13T13:00:59.767 に答える
1

これは私にとってはうまくいきます:

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>

角度:

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

$http から返された promise が保留中の間、ng-show はそれを「真実」であると評価します。約束が解決されると、これは自動的に更新されます...これはまさに私たちが望んでいることです。

于 2015-07-19T06:13:53.663 に答える
0

このようなことも試すことができます:

ディレクティブを作成:

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

次に、このようなものを mainCtrl に追加します

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

HTML は次のようになります。

<div class="buttons loader">
    <span class="icon" loader="isLoading()"></span>
</div>
于 2016-01-14T14:27:57.140 に答える
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);
  }
}
于 2015-02-12T15:23:49.793 に答える
0

DRYの概念を知っている場合、すべての答えは複雑であるか、すべてのリクエストにいくつかの変数を設定する必要があるか、非常に間違った方法です。ここでの簡単なインターセプターの例では、ajax の開始時にマウスを待機状態に設定し、ajax の終了時にマウスを自動に設定します。

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

アプリケーション構成にコードを追加する必要がありますapp.config。ロード状態でマウスを変更する方法を示しましたが、ローダーのコンテンツを表示/非表示にしたり、ローダーを表示しているいくつかの css クラスを追加、削除したりできます。

Interceptor はすべての ajax 呼び出しで実行されるため、すべての http 呼び出しで特別なブール変数( $scope.loading=true/false など)を作成する必要はありません。

于 2016-09-28T14:58:42.353 に答える
0

次のコードでディレクティブを作成します。

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

function toggleLoader(status){
  if(status.length){
    element.addClass('active');
  } else {
    element.removeClass('active');
  }
}
于 2015-04-08T09:14:27.363 に答える
0

次の方法では、すべてのリクエストを記録し、すべてのリクエストが完了すると非表示になります。

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

于 2016-02-25T08:55:38.653 に答える
0

http リクエスト呼び出しごとにローダーを表示する場合は、angular インターセプターを使用して http リクエスト呼び出しを管理できます。

ここにサンプルコードがあります

<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>
于 2018-04-03T14:05:43.107 に答える
0

これが私の実装で、ng-show とリクエスト カウンターと同じくらい簡単です。

$http へのすべてのリクエストに新しいサービスを使用します。

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

そして、現在の呼び出しの数に基づいてローダー ベースを使用できます。

<img data-ng-show="currentCalls > 0" src="images/ajax-loader.gif"/>
于 2017-04-07T09:25:16.053 に答える
-1

これが私の解決策であり、他の人がここに投稿したよりもはるかに簡単だと感じています。それがどれほど「きれい」かはわかりませんが、すべての問題を解決しました

「読み込み」と呼ばれるCSSスタイルがあります

.loading { display: none; }

ローディング div の html は何でもかまいませんが、いくつかの FontAwesome アイコンとスピン メソッドを使用しました。

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

非表示にしたい要素には、次のように記述します。

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

関数では、これをロード時に設定しました。

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

私はSignalRを使用しているので、hubProxy.client.allLocks関数で(ロックを通過したときに)突き出します

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

これは、ページの読み込み時に {{someField}} も非表示にします。これは、読み込み時にクラスを読み込み、AngularJS が後でそれを削除するためです。

于 2015-03-26T20:21:46.173 に答える