peta
peta

Reputation: 139

Hide form while loading data

In my AngularJS app I want to hide some page elements (sometimes all of them) until all async data is loaded.

Any suggestions on how to solve that when I have several data requests in the same controller?

I also would like to combine it with http://victorbjelkholm.github.io/ngProgress and find a solution with a service that listens to the status of dataLoaded (or whatever solution is best) that I can use in all different controllers of the app.

controller.js

$scope.dataLoaded = false;

dataFactory.getProduct(accessToken, storeId).then(function (response) {
    $scope.formData = response.data;
    $scope.dataLoaded = true;
}, function (error) {
    console.log('Error: dataFactory.getProduct');
});

dataFactory.getBrand().then(function (response) {
    $scope.brandData = response.data;
    $scope.dataLoaded = true;
}, function (error) {
    console.log('Error: dataFactory.getBrand');
});

service.js

app.factory("dataFactory", function ($http) {
var factory = {};

factory.getProducts = function (accessToken, storeId) {
    return $http.get('data/getProducts.aspx?accessToken=' + accessToken + '&storeId=' + storeId)
};

factory.getProduct = function (accessToken, storeId, productId) {
    return $http.get('data/getProduct.aspx?accessToken=' + accessToken + '&storeId=' + storeId + '&productId=' + productId)
};

factory.getBrand = function (accessToken, storeId) {
    return $http.get('data/getBrand.aspx?accessToken=' + accessToken + '&storeId=' + storeId)
};

return factory;

});

Upvotes: 0

Views: 279

Answers (1)

pedrommuller
pedrommuller

Reputation: 16056

what you can do is to resolve that function using your route provider with a combination of ng-cloak class that works like a charm, and also you can hide and show a "loader image" while you are switching routes.

let's say you have this service in your app:

app.factory("greetingService", function($q, $timeout){
   return {
       getGreeting: function(){
           var deferred = $q.defer();
           $timeout(function(){
               deferred.resolve("Allo!");
           },2000);
           return deferred.promise;
       }
   }
});

setting up the "resolve" function

.when("/anyroute", {
    templateUrl: "anyview.html",
    controller: "anyController",
    resolve: {
        greeting: function(greetingService){
            return greetingService.getGreeting();
        }
    }
})

in your controller:

app.controller("anyController", function ($scope, greeting) {
    $scope.greeting = greeting;
});

you can inject your "resolved" dependency right before your controller, that way you'll have the initial data when the controller loads.

for showing and hiding a loader you can do a directive like

angular.module('app').directive('loaderBar', function ($rootScope) {
    return {
        restrict: 'EA',
        replace: true,
        template: '<div class="showloader"><img src="loader.gif" alt="loading..." /></div>',
        link: function (scope, element) {
            var namedListener = $rootScope.$$listeners['$stateChangeStart'];
            if (namedListener === null || namedListener === undefined) {
                $rootScope.$on('$stateChangeStart', function () {
                    element.addClass('animatedLoader');
                });
                $rootScope.$on('$stateChangeSuccess', function () {
                  element.removeClass('animatedLoader');
                });
            }
        }
    };
});

and don't forget to use ng-cloak class to hide the contents while loading at the top of each view, that will work like a charm!

Upvotes: 1

Related Questions