Reputation: 139
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
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