118

Angularjs を使用して、ajax リクエストが完了するまでロード画面 (単純なスピナー) を表示する必要があります。コードスニペットでアイデアを提案してください。

4

15 に答える 15

209

データの読み込みステータスを示すスコープ変数を設定する代わりに、ディレクティブがすべてを実行するようにすることをお勧めします。

angular.module('directive.loading', [])

    .directive('loading',   ['$http' ,function ($http)
    {
        return {
            restrict: 'A',
            link: function (scope, elm, attrs)
            {
                scope.isLoading = function () {
                    return $http.pendingRequests.length > 0;
                };

                scope.$watch(scope.isLoading, function (v)
                {
                    if(v){
                        elm.show();
                    }else{
                        elm.hide();
                    }
                });
            }
        };

    }]);

このディレクティブを使用すると、読み込み中のアニメーション要素に「loading」属性を与えるだけで済みます。

<div class="loading-spiner-holder" data-loading ><div class="loading-spiner"><img src="..." /></div></div>

ページに複数の読み込みスピナーを配置できます。これらのスピナーをどこにどのようにレイアウトするかはあなた次第であり、ディレクティブは自動的にオン/オフを切り替えるだけです。

于 2013-10-28T06:04:20.860 に答える
56

これが例です。ブール値を使用した単純な ng-show メソッドを使用します。

HTML

<div ng-show="loading" class="loading"><img src="...">LOADING...</div>
<div ng-repeat="car in cars">
  <li>{{car.name}}</li>
</div>
<button ng-click="clickMe()" class="btn btn-primary">CLICK ME</button>

AngularJS

  $scope.clickMe = function() {
    $scope.loading = true;
    $http.get('test.json')
      .success(function(data) {
        $scope.cars = data[0].cars;
        $scope.loading = false;
    });
  }

もちろん、ローディング ボックスの HTML コードをディレクティブに移動して、$scope.loading で $watch を使用できます。その場合:

HTML :

<loading></loading>

ANGULARJS ディレクティブ:

  .directive('loading', function () {
      return {
        restrict: 'E',
        replace:true,
        template: '<div class="loading"><img src="..."/>LOADING...</div>',
        link: function (scope, element, attr) {
              scope.$watch('loading', function (val) {
                  if (val)
                      $(element).show();
                  else
                      $(element).hide();
              });
        }
      }
  })

プランク: http://plnkr.co/edit/AI1z21?p=preview

于 2013-06-17T09:47:02.553 に答える
21

これにはngProgressを使用します。

HTML にスクリプト/css ファイルを含めたら、依存関係に「ngProgress」を追加します。これを行うと、ルートの変更が検出されたときにトリガーされる、このようなものを設定できます。

angular.module('app').run(function($rootScope, ngProgress) {
  $rootScope.$on('$routeChangeStart', function(ev,data) {
    ngProgress.start();
  });
  $rootScope.$on('$routeChangeSuccess', function(ev,data) {
    ngProgress.complete();
  });
});

AJAX リクエストの場合、次のようなことができます。

$scope.getLatest = function () {
    ngProgress.start();

    $http.get('/latest-goodies')
         .success(function(data,status) {
             $scope.latest = data;
             ngProgress.complete();
         })
         .error(function(data,status) {
             ngProgress.complete();
         });
};

そうする前に、コントローラーの依存関係に「ngProgress」を追加することを忘れないでください。また、複数の AJAX リクエストを実行している場合は、メイン アプリ スコープでインクリメンタル変数を使用して、「ngProgress.complete();」を呼び出す前に AJAX リクエストがいつ終了したかを追跡します。

于 2014-04-04T03:26:35.413 に答える
7

これを行う最善の方法は、カスタムディレクティブと共に応答インターセプターを使用することです。$rootScope.$broadcastおよび$rootScope.$onメソッドを使用してpub/subメカニズムを使用すると、プロセスをさらに改善できます。

プロセス全体はよく書かれたブログ記事に記載されているので、ここでは繰り返しません。その記事を参照して、必要な実装を見つけてください。

于 2014-01-06T23:22:37.553 に答える
4

この回答を参考に

https://stackoverflow.com/a/17144634/4146239

私にとっては最善の解決策ですが、jQuery の使用を避ける方法があります。

.directive('loading', function () {
      return {
        restrict: 'E',
        replace:true,
        template: '<div class="loading"><img src="http://www.nasa.gov/multimedia/videogallery/ajax-loader.gif" width="20" height="20" />LOADING...</div>',
        link: function (scope, element, attr) {
              scope.$watch('loading', function (val) {
                  if (val)
                      scope.loadingStatus = 'true';
                  else
                      scope.loadingStatus = 'false';
              });
        }
      }
  })

  .controller('myController', function($scope, $http) {
      $scope.cars = [];
      
      $scope.clickMe = function() {
        scope.loadingStatus = 'true'
        $http.get('test.json')
          .success(function(data) {
            $scope.cars = data[0].cars;
            $scope.loadingStatus = 'false';
        });
      }
      
  });
<body ng-app="myApp" ng-controller="myController" ng-init="loadingStatus='true'">
        <loading ng-show="loadingStatus" ></loading>
  
        <div ng-repeat="car in cars">
          <li>{{car.name}}</li>
        </div>
        <button ng-click="clickMe()" class="btn btn-primary">CLICK ME</button>
  
</body>

$(element).show(); を置き換える必要があります。および(要素).show(); $scope.loadingStatus = 'true'; および $scope.loadingStatus = 'false';

それよりも、この変数を使用して要素の ng-show 属性を設定する必要があります。

于 2015-04-20T08:11:49.707 に答える
3

Restangular (素晴らしい) を使用している場合は、API 呼び出し中にアニメーションを作成できます。これが私の解決策です。rootscope ブロードキャストを送信する応答インターセプターと要求インターセプターを追加します。次に、その応答と要求をリッスンするディレクティブを作成します。

         angular.module('mean.system')
  .factory('myRestangular',['Restangular','$rootScope', function(Restangular,$rootScope) {
    return Restangular.withConfig(function(RestangularConfigurer) {
      RestangularConfigurer.setBaseUrl('http://localhost:3000/api');
      RestangularConfigurer.addResponseInterceptor(function(data, operation, what, url, response, deferred) {
        var extractedData;
        // .. to look for getList operations
        if (operation === 'getList') {
          // .. and handle the data and meta data
          extractedData = data.data;
          extractedData.meta = data.meta;
        } else {
          extractedData = data.data;
        }
        $rootScope.$broadcast('apiResponse');
        return extractedData;
      });
      RestangularConfigurer.setRequestInterceptor(function (elem, operation) {
        if (operation === 'remove') {
          return null;
        }
        return (elem && angular.isObject(elem.data)) ? elem : {data: elem};
      });
      RestangularConfigurer.setRestangularFields({
        id: '_id'
      });
      RestangularConfigurer.addRequestInterceptor(function(element, operation, what, url) {
        $rootScope.$broadcast('apiRequest');
        return element;
      });
    });
  }]);

ディレクティブは次のとおりです。

        angular.module('mean.system')
  .directive('smartLoadingIndicator', function($rootScope) {
    return {
      restrict: 'AE',
      template: '<div ng-show="isAPICalling"><p><i class="fa fa-gear fa-4x fa-spin"></i>&nbsp;Loading</p></div>',
      replace: true,
      link: function(scope, elem, attrs) {
        scope.isAPICalling = false;

        $rootScope.$on('apiRequest', function() {
          scope.isAPICalling = true;
        });
        $rootScope.$on('apiResponse', function() {
          scope.isAPICalling = false;
        });
      }
    };
  })
;
于 2015-03-09T11:44:04.993 に答える
3

これを「app.config」に含めます。

 $httpProvider.interceptors.push('myHttpInterceptor');

そして、次のコードを追加します。

app.factory('myHttpInterceptor', function ($q, $window,$rootScope) {
    $rootScope.ActiveAjaxConectionsWithouthNotifications = 0;
    var checker = function(parameters,status){
            //YOU CAN USE parameters.url TO IGNORE SOME URL
            if(status == "request"){
                $rootScope.ActiveAjaxConectionsWithouthNotifications+=1;
                $('#loading_view').show();
            }
            if(status == "response"){
                $rootScope.ActiveAjaxConectionsWithouthNotifications-=1;

            }
            if($rootScope.ActiveAjaxConectionsWithouthNotifications<=0){
                $rootScope.ActiveAjaxConectionsWithouthNotifications=0;
                $('#loading_view').hide();

            }


    };
return {
    'request': function(config) {
        checker(config,"request");
        return config;
    },
   'requestError': function(rejection) {
       checker(rejection.config,"request");
      return $q.reject(rejection);
    },
    'response': function(response) {
         checker(response.config,"response");
      return response;
    },
   'responseError': function(rejection) {
        checker(rejection.config,"response");
      return $q.reject(rejection);
    }
  };
});
于 2015-03-19T12:30:24.840 に答える
2

Angularjsまた、プロジェクトでアニメーションを使用する方法を示す素晴らしいデモもあります。

リンクはこちら (左上隅を参照) .

それはオープンソースです。ここにダウンロードへのリンクがあります

そして、ここにチュートリアルへのリンクがあります。

要点は、先に進んでソース ファイルをダウンロードし、スピナーがどのように実装されているかを確認することです。彼らはもう少し良いアプローチを使ったかもしれません。だから、このプロジェクトをチェックしてください。

于 2013-06-17T10:00:51.623 に答える
2

angular-busyを使用します。

アプリ/モジュールに cgBusy を追加します。

angular.module('your_app', ['cgBusy']);

あなたの約束をに追加してくださいscope

function MyCtrl($http, User) {
  //using $http
  this.isBusy = $http.get('...');
  //if you have a User class based on $resource
  this.isBusy = User.$save();
}

HTML テンプレートで:

<div cg-busy="$ctrl.isBusy"></div>
于 2016-02-29T18:26:44.693 に答える
1

ここでの簡単なインターセプターの例では、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 など) を作成する必要はありません。

インターセプターは組み込みの angular jqLit​​e https://docs.angularjs.org/api/ng/function/angular.elementを使用しているため、Jquery は必要ありません。

于 2016-09-28T15:12:55.730 に答える
1

show 属性と size 属性を使用してディレクティブを作成します (さらに追加することもできます)。

    app.directive('loader',function(){
    return {
    restrict:'EA',
    scope:{
        show : '@',
      size : '@'
    },
    template : '<div class="loader-container"><div class="loader" ng-if="show" ng-class="size"></div></div>'
  }
})

そしてhtmlで次のように使用します

 <loader show="{{loader1}}" size="sm"></loader>

show変数では、promise が実行されているときに true を渡し、リクエスト完了したときにfalseにします。アクティブなデモ - JsFiddle の Angular Loader ディレクティブのサンプル デモ

于 2017-05-23T07:49:49.520 に答える