简体   繁体   中英

Spinner in Angular.js

I want to use a spinner which I can show during some of the rest api calls for a better UX. I have come across many existing github projects which does exactly similar things.

https://github.com/cgross/angular-busy
https://github.com/urish/angular-spinner

But I'm not able to use any of the existing projects. I think before I start writing something of my own, I want to know if things which I'm looking for can be done using these projects or any other existing project.

Requirement:

  1. During some of the rest api calls like uploading images, fetching some data, deleting images, etc, I want to show a spinner with background faded. Once I have the result, I can show the background again and remove the spinner.
  2. I want to use this spinner with start/stop from my controller not from my html.
  3. I don't want this spinner for all the xhr requests by default.

I think angular-busy demo does solves most of the above requirements except that it needs a promise param in html. Is there anyway by which I can control the start/stop dynamically from my controller rather than giving a promise.

Angular-spinner demo is good but it doesn't fade out background. Is there any way to fade out background ?

Can anyone give me some pointers how exactly can I solve my problem ?

I always create my own spinner with this logic:

js:

app.directive('ngSpinnerBar', ['$rootScope',
    function ($rootScope) {
        return {
            link: function (scope, element, attrs) {
                // by defult hide the spinner bar
                element.addClass('hide'); 

                // count how many time requests were sent to the server
                // so when they all done the spinner will be removed
                scope.counter = 0;

                $rootScope.$on('$stateNetworkRequestStarted', function () {
                    scope.counter++;
                    element.removeClass('hide'); // show spinner bar
                    //  $('body').addClass('page-on-load');
                });

                $rootScope.$on('$stateNetworkRequestEnded', function () {
                    scope.counter--;
                    if (scope.counter <= 0) {
                        scope.counter = 0;
                        element.addClass('hide'); // show spinner bar
                        //  $('body').removeClass('page-on-load'); // remove page loading indicator
                    }

                });

            }
        };
    }
])

html:

<div ng-spinner-bar></div>

As you can see every time i send a request to the api i show the spinner (css create the spinning - link ) and when result come back i send event to hide the spinner.

if you want to make things easier for you, you should create a service which send all the api requests (wrap $http). that way you can ensure every request will show the spinner.

EDIT

the first result in google gave me this - fade background in angular

It seems like http://bsalex.github.io/angular-loading-overlay/_site/ fits the requirements.

For example:

 var app = angular.module('app-http-integration-with-reference-id-and-matchers', [ 'bsLoadingOverlay', 'bsLoadingOverlayHttpInterceptor' ]) .factory('randomTextInterceptor', function(bsLoadingOverlayHttpInterceptorFactoryFactory) { return bsLoadingOverlayHttpInterceptorFactoryFactory({ referenceId: 'random-text-spinner', requestsMatcher: function(requestConfig) { return requestConfig.url.indexOf('hipsterjesus') !== -1; } }); }) .factory('randomUserInterceptor', function(bsLoadingOverlayHttpInterceptorFactoryFactory) { return bsLoadingOverlayHttpInterceptorFactoryFactory({ referenceId: 'random-user-spinner', requestsMatcher: function(requestConfig) { return requestConfig.url.indexOf('randomuser') !== -1; } }); }) .config(function($httpProvider) { $httpProvider.interceptors.push('randomTextInterceptor'); $httpProvider.interceptors.push('randomUserInterceptor'); }).run(function($sce, bsLoadingOverlayService) { bsLoadingOverlayService.setGlobalConfig({ /* It is only an example, don't use this url in production. Copy this template to your code base or use integration with Spin.js (see Docs & Examples) */ templateUrl: $sce.trustAsResourceUrl('https://raw.githubusercontent.com/bsalex/angular-loading-overlay/gh-pages/_site/loading-overlay-template.html') }); }); app.controller('HttpIntegrationWithReferenceIdAndMatchersController', function($scope, $http, $sce, bsLoadingOverlayService) { $scope.randomText = $sce.trustAsHtml('Fetch result here'); $scope.randomUser = undefined; $scope.fetchRandomText = function() { $http.get('http://hipsterjesus.com/api/') .success(function(data) { $scope.randomText = $sce.trustAsHtml(data.text); }) .error(function() { $scope.randomText = $sce.trustAsHtml('Can not get the article'); }); }; $scope.fetchRandomUser = function() { $http.get('https://randomuser.me/api/') .success(function(data) { $scope.randomUser = data.results[0]; }); }; }); 
 .random-result { display: flex; height: 170px; margin-top: 1em; } .random-result__text, .random-result__user { position: relative; overflow: auto; border: 2px dashed #C00; flex: 1; margin: 0.5em; padding: 0.5em; text-align: center; } .user__photo { width: 100px; height: 100px; border-radius: 50%; margin: 0; } .user__name { font-size: 1.5em; margin: 0.5em; padding: 0; text-align: center; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script> <script src="https://rawgit.com/bsalex/angular-loading-overlay/master/dist/angular-loading-overlay.js"></script> <script src="https://rawgit.com/bsalex/angular-loading-overlay-http-interceptor/master/dist/angular-loading-overlay-http-interceptor.js"></script> <div ng-app="app-http-integration-with-reference-id-and-matchers"> <div ng-controller="HttpIntegrationWithReferenceIdAndMatchersController"> <div class="well well-lg bs-loading-container"> <button ng-click="fetchRandomText()">Fetch random text</button> <button ng-click="fetchRandomUser()">Fetch random user</button> <div class="random-result"> <div class="random-result__text" bs-loading-overlay bs-loading-overlay-reference-id="random-text-spinner" bs-loading-overlay-delay="3000"> <p ng-bind-html="randomText"></p> </div> <div class="random-result__user user" bs-loading-overlay bs-loading-overlay-reference-id="random-user-spinner" bs-loading-overlay-delay="3000"> <div ng-if="randomUser"> <img ng-src="{{randomUser.picture.large}}" alt="" class="user__photo" /> <p class="user__name"> {{randomUser.name.first}} {{randomUser.name.last}} </p> </div> </div> </div> </div> </div> </div> 

In the snippet above I've used integration with $http service. It matches requests and shows spinner with specified referenceId .

Also, the following features are available:

  • You can show and hide spinners from controllers injecting bsLoadingOverlayService and calling bsLoadingOverlayService.start(); and bsLoadingOverlayService.stop(); ;
  • You can wrap Promises to show and hide spinners with bsLoadingOverlayService.wrap() ;
  • You can create preconfigured handlers ( bsLoadingOverlayService.createHandler({referenceId: 'handler-overlay'}); ), to keep options in one place and then just call preconfiguredHandler.start(); and preconfiguredHandler.stop();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM