Reputation: 727
I have an issue with a $scope.$watch
not getting evaluated after a call to retrieve my data model. I'll explain, but for the impatient, maybe you can figure out what's going on based on this fiddle: http://jsfiddle.net/ADukg/3964/.
In our Angular project, we let some directives build their own data model, which is also sometimes passed down to other, contained directives. In this case, the directive building its own model is myMessages
, and the directive to which its data is passed is myObjects
.
The myMessages
directive relies on a service called messageManager
to get the messages relevant for it at any time (in our code, this is based on things like $routeParams
values, e.g., http://localhost/messages/34
). For my example, I just ignored the parameters and passed back the data directly.
The interesting part is that, if I comment out lines 55 and 68 (the wrapping setTimeout
call), this code works "fine" (I put it in quotes because, well, I'm really not sure if it's actually using good practices or not). However, keeping the call there to simulate the HTTP request, the value of the objects
scope variable in the myObjects
directive's link
method is empty, and the watch set up against the variable fails to run after 2 seconds.
I tried to trick the watch to re-evaluate by explicitly calling $scope.$apply
both around the call to ctrl.loadData()
and inside the actual loadData
method, but received this error:
$digest already in progress
Looking through the docs, it seems as though that's correct, because we're still within the Angular context when we do these calls (we're using ngResource inside a service, so it's not calling out to some jQuery context or anything strange). I just can't seem to get the watch against the objects
variable to re-evaluate after the data has been populated, no matter what I try (including setting the third parameter to the $scope.$watch
function to true
).
Any help would be very much appreciated.
Upvotes: 2
Views: 593
Reputation: 54514
You should use $timeout
instead of setTimeout
since $timeout
will trigger a digest cycle to make the data available in the binding.
myApp.factory('messageManager', function ($q, $timeout) {
return {
getMessages: function () {
var deferred, promise;
deferred = $q.defer();
promise = deferred.promise;
$timeout(function () {
deferred.resolve({
messages: [{
firstName: 'Sam',
lastName: 'Rockwell',
}, {
firstName: 'Nat',
lastName: 'Faxon',
}, {
firstName: 'Jim',
lastName: 'Rash'
}]
});
}, 2000);
return promise;
}
};
});
Upvotes: 2