This is a follow up to my previous AngularJS question.
I am trying to replicate the functionality of the $resource service that is mentioned in this video tutorial: link.
In this tutorial, it is shown that you can update a scope variable and its view using an asynchronous call. First, here's the resource that's set up:
$scope.twitter = $resource('http://twitter.com/:action',
{action: 'search.json', q: 'angularjs', callback: 'JSON_CALLBACK'},
{get: {method: 'JSONP'}});
Then the get
function is called on the resource to make the ajax call and update the necessary scope variable:
$scope.twitterResult = $scope.twitter.get();
What's happening here is that $scope.twitter.get()
immediately returns an empty object reference. Then, when the ajax request returns, that object is updated with the data from Twitter. The view then updates all {{twitterResult}} instances and you see the data that was returned.
What I don't get is, when the object is updated in the asynchronous callback, how does the scope know that the value has changed?
I don't think it does - the callback must call some kind of update function on the scope, right? But if so, how is this done? I have heard of a function called $apply
that might be the answer - but how do you reference $scope.$apply() from inside the resource?
I have created a JSFiddle to illustrate the problem: http://jsfiddle.net/Qcz5Y/10/
(Edit: Here is a newer JSFiddle with a different async call to illustrate the problem using an ajax call instead of setTimeout: http://jsfiddle.net/Qcz5Y/14/)
In this example, you will see a controller and a resource. The controller's scope has a property, fruit
, which starts out set to an object. When you click 'Get new fruit', that property is set to fruitResource.get()
, which immediately returns an empty object. It then makes an asynchronous call, and finally executes a callback which updates the value of the object that was originally returned.
When this happens, the value of $scope.fruit
is properly updated to what was set in the callback. But it isn't reflected in the view.
If you click "Print current fruit", it will log to the console the current value of $scope.fruit
. This was just for checking; it has the side-effect of updating the view.
I feel like I need to be doing something like $scope.$apply() at the bottom of the get_callback
function (you'll see it in the code). Would that be the right thing to do? If so, how do I get a reference to $scope inside the fruitResource? I know I can probably pass $scope
into fruitResource.get()
as a parameter and then reference it that way, but the $resource.get() function in the example mentioned at the top doesn't need to do this, so I was hoping that AngularJS provides some way to get the scope from services automatically.
Thanks!
I figured out that you can pass $rootScope
into a service and then call $apply
on that. So when you want to update your view, you just do $rootScope.$apply()
.
Here is the updated JSFiddle: http://jsfiddle.net/Qcz5Y/11/
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