This is a similar question to this one. I'm still seeing some issues with asynchronous data in my directives. Basically I have directives that I want to pass data into, and this data is fetched asynchronously. I started doing this with the scope property on the directive like this:
scope: {
myAsyncData: '='
}
In the link function I added a $watch
so I could update my model based on a value is in the scope. Something like this:
scope.$watch(scope.foo, function() {
//logic based on myAsyncData
}
When I did this, I started getting javascript errors because the asynchronous data hadn't returned yet. This is what prompted me to post the question linked above. So, I then changed my $watch
to something like this:
scope.$watch(scope.foo, function() {
if (angular.isDefined(scope.myAsyncData))
{
//logic based on myAsyncData
}
}
When I do this, I don't get the javascript errors. However, the $watch
doesn't get run again when the data is returned, and so my view doesn't reflect the model correctly. I tried assigning$scope.foo
in a $timeout
to trigger the watch after the data is returned, but that seems too dependent on timing and is not very robust.
My question is just what is the correct way of interacting with asynchronous data in the directive? I've seen some examples that get the data in the directive like this:
scope.$eval(attrs.myAsyncData);
This doesn't seem to change anything. Is there anything fundamentally different with this than the myAsyncData: '='
above?
I've started to wonder if I should just get the data through services, but it seems like there would be the exact same issues. I've also had the thought of getting the data directly in the directive, but I don't want to directive to be responsible for getting the data. I only want the directive to be responsible for displaying the data and updating the view as the user interacts with it.
I may be missing something obvious on how this should be done, so any input would me much appreciated.
A little bit late - but I came accross this post with the same problem and resolved it by providing my $watch
call's watchExpression
parameter as a function.
scope.$watch(function() {
return scope.foo;
},
function() {
//logic based on myAsyncData
}
);
I couldn't understand very well the Misko Hevery's answer so I decided to use events, and they worked well for me.
In my controller, I loaded the data like this:
$http({method: 'GET', url: 'js/datasets/ips-processed.json'}).
success(function(data, status, headers, config) {
//post load code here and...
$scope.$broadcast("Data_Ready");
In my directive, I put
return {
restrict: 'A',
scope: {
donutid: "=",
dataset: "="
},
link: function(scope, elements, attrs) {
scope.$on("Data_Ready", function (){
//here the functionality for this directive
Hope it helps to someone.
Came across this answer looking for a solution to the same problem.
After much research, suggest that your use Misko Hevery's solution here to delay loading of the Controller until loading of the XHR has 'resolved'.
This seems to have solved all of my 'asynchronous data loading in Directives' issues.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With