在AngularJS中的$ http请求期间显示微调框G​​IF?


234

我正在使用$httpAngularJS 的服务来发出Ajax请求。

在执行Ajax请求时如何显示微调器GIF(或其他类型的忙碌指示器)?

ajaxstartevent在AngularJS文档中看不到任何类似的内容。


2
如果您想要一个基于HTTP Interceptor的简单微调器,我为此提供了一个angular模块。它使用了流行的“ Identified Sham”微调器。看一下: github.com/harinair/angular-sham-spinner
Hari Gangadharan

1
我编写了一个插件angular-httpshooter,它在调用射击之前释放了一个包含配置数据的事件,并在接收到reposne之后释放了一个事件,您可以编写捕获这些事件的全局加载程序
Siddharth

Answers:


88

这是当前过去的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']).
//.......

这是其余的(HTML / CSS)....使用

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

切换它。注意:以上内容在发布开始时用于角度模块

#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
请注意,您可以使用angular.element('#mydiv').show(),而不是$('#mydiv').show()
JMaylin

8
如果您的页面发出多个ajax请求,则此方法不起作用。在第一个请求结束后,它将隐藏加载的gif。
Meeker 2013年

38
根据AngularJS的最佳做法(该做法违反了公认的解决方案),您不应在指令之外修改DOM。考虑从指令中的元素上调用show / hide。
Mariusz 2014年

7
我不确定我是否知道要发表评论...但是使用ng-class指令而不是使用JQuery显示和隐藏元素不是正确的方法吗?
James Heald

2
@JamesHeald是正确的..您绝对不需要真正在Angular中使用jQuery进行任何dom操作。调查:ng-class,ng-if,ng-hide,ng-show等。几乎所有需要的指令都有。
jKlaus

471

这实际上取决于您的特定用例,但是一种简单的方法将遵循以下模式:

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

223
如果您同时有多个ajax请求,则可以将其声明loading为整数$scope.loading = 0;,在请求开始时执行$scope.loading++;,在结束时执行$scope.loading--;。模板中没有任何更改。因此,在至少有一个请求正在进行时,显示微调

16
您还应该在错误后备功能中将loading设置为false。
sebnukem 2014年

3
@sebnukem是的。这是一个相当高级的示例,但是为了清晰起见,我还是继续添加了它。感谢您的反馈!
2014年

1
@JMaylin-然后您可以在$ scope.loading上使用$ watch做其他事情
Jason

5
一种更简洁的方法,而不是$scope.loading = false同时放入成功和失败回调,是将其放入中.finally()。它看起来像:mySvc.get().then(success, fail).finally(function() { $scope.loading = false; });
Tom

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

有关编写拦截器的更多信息


@punkrockpolly在我的特定情况下,我有两个单独的组件调用服务。但这仅适用于其中的一个,是否应该传递参数或使之可重用的东西?
RicardoGonzales 2015年

@razorblade它将$http在您通过任何服务拨打电话时旋转。
punkrockpolly

31

如果您使用的是ngResource,则对象的$ resolved属性对加载程序很有用:

对于如下资源:

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

您可以将加载程序链接到资源对象的$ resolved属性:

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


13

刚刚发现了angular-busy根据一些异步调用显示一个小的加载程序的指令。

例如,如果您必须制作一个GET,请在中引用诺言$scope

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

并这样称呼它:

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

这是GitHub

您也可以使用bower(不要忘记更新项目依赖项)安装它:

bower install angular-busy --save

我在文档中找不到如何“禁用某些元素”。你能解释一下吗?例如,我想在显示微调器时禁用按钮。
c4k 2015年

angular-busy只会在您的元素上放置一个蒙版,我认为您不能像想要的那样禁用按钮,但是您可以使用一个空模板在其上设置背景以给人一种印象。我不是母语人士,为您带来的困惑感到抱歉:)
Balthazar 2015年

好的,我编辑了您的答案,以防止其他人也有同样的困惑。一个会说法语的英语总是和另一个法语混淆:)
c4k 2015年

5

如果将api调用包装在服务/工厂内,则可以在此处跟踪加载计数器(每个答案和@JMaylin的出色同时建议),并通过指令引用加载计数器。或其任何组合。

API包装

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

纺纱指令

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

用法

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

5

对于页面加载和模态,最简单的方法是使用ng-show指令并使用范围数据变量之一。就像是:

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

在这里,尽管someObject未定义,微调器将显示。服务返回数据并someObject填充后,微调框将返回其隐藏状态。


3

我猜这是添加微调器的最简单方法:

您可以将ng-show与以下任何一个精美的微调框的div标签一起使用 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


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>

添加此CSS:

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

只需在您的角度添加:

$ rootScope.loading = false; $ rootScope.loading = true; -> $ http.get结束时。


2

分享我来自@bulltorious的出色答案的版本,针对较新的角度构建进行更新(我在此代码中使用1.5.8版),还合并了@JMaylin使用计数器的想法,以便对多个同时请求具有鲁棒性,并且跳过显示动画的选项,该请求所用的时间少于最小的毫秒数:

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请求调用

  <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

没有拦截器或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完成时。


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返回的承诺尚未完成时,ng-show会将其评估为“真实”。诺言一旦解决,它就会自动更新……这正是我们想要的。


这不是动态的方法。
Umair Hamid

您能否解释一下为什么您认为这不是实现此目标的动态方式。这将帮助其他阅读此文章的人学习。谢谢。
dank

我的申请中有多个要求。$ scope.req仅适用于单个请求。当此特定请求完成时,完整的加载器将隐藏,并且不会等待完成其他请求。实现此目的的最佳方法是使用拦截器。
Umair Hamid

1

使用以下拦截器来显示HTTP请求上的加载栏

'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
仅代码的答案不是很有用。
Phantômaxx

0

使用以下代码创建指令:

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

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

0

显示不同URL更改之间的加载的另一种解决方案是:

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

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

然后在标记中使用切换微调器ng-show="loading"

如果要在ajax请求上显示它,只需$scope.loading++在请求开始时和结束时添加即可$scope.loading--


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>

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


0

由于position:fixed的功能最近发生了变化,因此我很难在所有元素上方显示gif加载器,因此我不得不使用angular的内置jQuery

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

控制者

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

})

希望这可以帮助 :)


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

必须在应用程序config中添加代码app.config。我展示了如何在加载状态下更改鼠标,但是在其中可以显示/隐藏任何加载程序内容,或者添加,删除一些显示加载程序的CSS类。

拦截器将在每个ajax调用上运行,因此无需在每个http调用上创建特殊的布尔变量($ scope.loading = true / false等)


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

0

如果您想为每个http请求调用显示加载程序,则可以使用角度拦截器来管理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>

0

只需使用ng-show和一个布尔值

无需使用指令,无需复杂。

这是放置在“提交”按钮旁边或您希望微调器位于任何地方的代码:

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

然后在您的控制器中:

$scope.dataIsLoading = true

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

-1

这是我的解决方案,我认为这比其他发布的解决方案要容易得多。虽然不确定它有多“漂亮”,但是它解决了我所有的问题

我有一个称为“加载”的CSS样式

.loading { display: none; }

加载div的html可以是任何东西,但我在其中使用了一些FontAwesome图标和spin方法:

<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随后将其删除。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.