Hey guys so I am simply trying to load data when my app starts. However, the view loads faster than the http request(of course). I want to refresh my view once my data has been properly loaded because that data defines my view.
I've tried $rootScope.apply from inside the factory where I do my http request, and I also tried directly doing the http request in my controller again with $scope.apply, and neither one worked as they both gave me "$digest already in progress"
Any idea how can I set up my code to make my views refresh on data load? I will be having several different http requests and I would like to know how to set them up properly! I would really appreciate any input!
Here is some of the code I am working with.
app.factory('HttpRequestFactory', function($http, $q) {
var HttpRequestFactory = {
async: function(url, params) {
var deferred = $q.defer();
$http({
url: url,
method: post,
params: params
})
.success(function(data, status, headers, config) {
deferred.resolve(data);
})
.error(function(data, status, headers, config) {
deferred.reject("An error occurred");
});
return deferred.promise;
}
};
return HttpRequestFactory;
});
Factory
function initializeAll(){
HttpRequestFactory.async('../api', {action: 'getall'}).then(function(data) {
//$rootScope.$apply(function () {
allData = data;
//});
angular.forEach(allData, function(value, index){
console.log('Voala!');
});
});
}
Controller calling the factory's function initializeAll()
app.controller("MainController", ["$scope", "$rootScope","MyFactory",
function($scope, $rootScope, MyFactory){
MyFactory.initializeAll();
}
]);
Don't use
$apply
: use$watch
.Calling
$apply
is (almost) always the wrong thing to do. The only time you should ever be calling it is if you've triggered a change outside of an 'angular' method; here, since the trigger occurs in an angular$http
request, you can't call$apply
because it's already being done at that moment by the$http
block. Instead, what you want to do is$watch
.Official Doc for $scope.$watch() here
This will let you watch an object and update whenever it changes. I assume that your view is based on
allData
and you want it to update immediately; if you're using anng
method, then the watch is automatically setup for you and no more work should be needed. If you're usingallData
yourself inside a controller, you can write the watch in that controller like this:Oh my !
You got the f** matter with AngularJS !
In fact you have to do a "safeApply" like that for example :
In AngularJS you can only have one $apply or $digest loop at the same time.
For details on these loops look at the docs : http://docs.angularjs.org/guide/concepts
It will explain what is the $apply loop and you'll understand a lot of things about the two-way-data-binding in AngularJS
Hope it helps.