0
votes

How can I achieve the following in AngularJS:

enter image description here

If I have my page that will show some widgets and each widget has a button called refresh. When the button is clicked then the content of that widget is reloaded from server. While the content is reloaded I want to show the user a message within that widget, please wait ... with a possible fading effect.

How can I achieve that in AngularJS?

I kind of taught about having a common service for that purpose and then somehow each widget controller will use that service or something like that, maybe also a directive that will show the actual loading/please wait message?

What is your advise?

P.S. There should be also a loading/please wait message with fading for the whole page, when the route is changing ... like switching between pages.

3
fairly easy to acheive using ng-show or ng-class and a boolean variable scoped per widget such as in a directive - charlietfl

3 Answers

4
votes

In my recent project I'm using https://github.com/cgross/angular-busy

Very nice thing, all you have to do is put your promise into $scope, and then add cg-busy attr to your element which should have spinner (beside registering module obviously):

Controller:

$scope.myPromise = restangular.get('something',12).then(function(response) { ... })

Html:

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

You can also customize template that's gonna be displayed (which includes spinner and text message).

2
votes

there are implementations of this available on github : angular-spinner or angular-sham-spinner. Read this BLOG which details how the spinner works with angularjs

if you want to implement it yourself to be reusable...

app.directive("spinner", function(){
    return: {
        restrict: 'E',
        scope: { enable: "=" },
        template: '<div class="spinner" ng-show="enable"><img src="content/spinner.gif"></div>'
    }
});

i havent tested the code but directive wont be more complex than above...

1
votes

As harish point out the right way would be a directive, but theres no need if you want of include another dependency, you could do something like this

  1. You can create a nice CSS3 only loading (so not images required) animation with the help of CssLoad

  2. Create a directive with a linking function so you can call and stop the animations within your controller the angular way:

    .directive('appLoading', function(){
        return {
            restrict: 'E',
            templateUrl: 'template-file.html', // or template: 'template html code inline' Display none to the code is important so is not visible if youre not caling the methods
            replace: true,
            link: function(scope, elem) {
                scope.$on('app-start-loading', function(){
                    elem.fadeIn(); //asumming you have jquery otherwise play with toggleClass and visible and invisible classes
                });
                scope.$on('app-finish-loading', function(){
                    elem.fadeOut();
                });
            }
         }
     })
    
  3. Include in your html code the directive: <app-loading></app-loading>

  4. Now all you need to do is call the scope methods in your controller like this:

    $scope.$broadcast('app-start-loading'); // to start the loading animation

    $scope.$broadcast('app-finish-loading'); // to stop the animation

NOTE: if all your widgets share a scope, the loading may be triggered in all of them