3

I'm doing an AJAX request for data that is used in the view for generation of a list. I need to know when the $scope is updated and when the view is rendered after a successful response received, so that I can set dynamically some initial values and some event handlers for the list.

I'm currently using the following code which is not doing the trick:

responsePromise.success(function (data, status, headers, config) {
    var slideInfos = data;
    $scope.slideInfos = slideInfos;
    setInitialSliderValues();
});

At the time I call setInitialSliderValues() the view is still not refreshed.

When I try using the following I get an error "$digest already in progress":

responsePromise.success(function (data, status, headers, config) {
    var slideInfos = data;
    $scope.$apply(function () {
        $scope.slideInfos = slideInfos ;
        setInitialSliderValues();
    }
});

How can I be absolutely sure that changes to the data have taken effect on the page without the use of a timer that checks for the changes I expect.

Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
Galya
  • 6,294
  • 6
  • 27
  • 45

2 Answers2

9

Use $timeout() that will get run in the next digest cycle. Don't forget to add $timeout dependency on controller.

$timeout(function () {
    $scope.slideInfos = slideInfos ;
    setInitialSliderValues();
});
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
1

You can try using $evalAsync:

responsePromise.success(function (data, status, headers, config) {
    $scope.slideInfos = data;
    $scope.$evalAsync(function () {        
        setInitialSliderValues();
    }
});

Unlike $timeout, it will try to fire within the same digest cycle if possible, if not it will be resolved in the next digest-cycle.

Kjell Ivar
  • 1,154
  • 8
  • 8
  • This is a nice trick, but it won't be the answer in my case because this happens very quickly (the ajax request is finished when the rendering of the whole page is still in progress) and the currently working digest is not the one I wait for (or at least I presume this is why it doesn't work). – Galya Feb 28 '15 at 21:16
  • @kjell Ivar AFAIK `$timeout` and `$evalAsyc` both works as the same, only $timeout is different because we can tell to run digest cycle after a particular interval of time..Correct me if I'm wrong.. – Pankaj Parkar Feb 28 '15 at 21:19
  • It will be resolved at the end of the digest, as its put in an Async-queue. Did you try it? @pankajparkar they don't work the same. You can read more about the differences here: http://www.bennadel.com/blog/2605-scope-evalasync-vs-timeout-in-angularjs.htm – Kjell Ivar Feb 28 '15 at 21:19
  • @KjellIvar "If you truly want to execute code at a later point in time, use $timeout()".. he didn't say $timeout will execute in between, while your digest cycle is in progress – Pankaj Parkar Feb 28 '15 at 21:25
  • @KjellIvar, Yes, I tried id and setInitialSliderValues() is still called when the slides are 0 (it means that the view is not updated with the new data). – Galya Feb 28 '15 at 21:26