Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update Scope With SetInterval / SetTimeout

I'm trying to create a "Clock" directive as a way to learn Angular. How would I go about making sure it "ticks?"

Here's what I tried fiddle Link:

angular.module('app')
.directive('clock' , function(){
  return {
    restrict: 'E',
    template: '<div>{{date}}</div>',
    link: function(scope, elem, attr){
      scope.date = getDate();
      setInterval(function(){
        scope.date = getDate();
      }, 100);
    }
  }
})

Using setInterval to upate the scope variable isn't working. I'm assuming because the directive isn't watching for it to be changes anymore?

like image 794
Pharylon Avatar asked Sep 17 '15 16:09

Pharylon


1 Answers

It is updating the scope variable, but Angular isn't aware of the change.

It is recommended to use Angular $interval.

Here is your fiddle with $interval: https://jsfiddle.net/oafcde6g/11/

In other words, Angular doesn't do any magic by "listening" to scope properties, it simply does dirty-checking. But to do it, it needs to be notified that something changed. So if you really wanted to use setInterval instead of $interval, you could notify it manually that something changed:

setInterval(function () {
    scope.$apply(function () {
        scope.date = getDate();
    });
});

This way, you're notifying it to run your anonymous function inside $apply and then digest the scope, checking if anything changed. If it did, it will update the view.

"Magic" of ng-* events (ng-click, ng-model etc)

Even though it looks like angular automatically knows to rerender the view when you click/change something by using it's built-in directives, it really isn't so.

Some simple implementation of ng-click would look something like:

angular.module('app')
.directive('ngClick' , function(){
  return {
    restrict: 'A',
    link: function(scope, elem, attr){
        elem.on('click', function () {
            scope.$apply(function () {
                scope.$eval(attr.ngClick);
            });
        });
    }
  }
})

You can see this for yourself if you try to bind click event normally, outside of angular context and make it change a scope variable. It won't update until you explicitly tell it to (like we did in setInterval example).

like image 55
Igor Pantović Avatar answered Sep 21 '22 21:09

Igor Pantović