Stafford Williams Stafford Williams - 2 months ago 19
AngularJS Question

Update md-progress-linear without triggering $digest

The demo of

md-progress-linear
declares the following;

<md-progress-linear md-mode="determinate" value="{{vm.determinateValue}}">
</md-progress-linear>


And then updates it like this;

$interval(function() {
self.determinateValue += 1;
if (self.determinateValue > 100) self.determinateValue = 30;
}, 100);


This however will trigger a
$digest
every 100 milliseconds, causing all watches and bindings etc to additionally be updated every 100 milliseconds.

Is there a way to display a smoothly animated, determinate
md-progress-linear
without needing to trigger a
$digest
on each tick?

Answer

This is not exactly true :

$interval triggers an $apply call, not a $digest. The difference is (basically) that an $apply call will cause all watches from the whole scope tree to be checked (from $rootScope), where a $digest only target a given scope (and it's children)

If you know that the method called by interval will only impact a given scope tree ( aka : the scope and it's children tree ) and not the whole rootScope tree, you can, to improve performances, do this instead :

$interval(function() {
      self.determinateValue += 1;    
      if (self.determinateValue > 100) self.determinateValue = 30;
      $scope.$digest();
    }, 100, 0, false);

the 'false' 4th param is "invokeApply=false", asking NOT to call $rootScope.apply after the method execution. Instead, you are manually calling $digest on you scope at the end of the method (you could even trigger the digest only if your condition is true, avoiding the digest cycle when your handler does nothing).

(the third param is the repeat count, and is needed to add the 4rth parameter.. 0 -> infinite repeat, as if called with only 2 params)

Note that, as said, the code sample will work, given that the md-progress-linear directive's scope is the $scope or one of it children.

This is the best you can do, as there is no way to ask md-process-linear to updates without a $digest cycle.

(With a custom directive, you could have worked your way with events instead of watch, but for this need, this seems overcomplicated, calling targeted $digest instead of $apply is, most of the time, really enough, performance-wise)