0

Is this the way to achieve read-only binding to an object attached in a parent directive's scope?

I really need the child directive to receive change notifications if the parent changes it's "$scope.thing".

Basically, I'm polling right now. I'd like a callback method.

angular.module('plunker', [])
.directive('myParent', function($compile) {
  return {
    controller: function($scope, $log) {
      $scope.thing = { awesome: 'sucky' };
      var count = 0;
      setInterval(function() { $scope.thing = { awesome: 'cool'+count++ }}, 2000); 
    },
    template: '<div><div my-child entity="thing"></div></div>'
  };
})
.directive('myChild', function($parse, $log) {
  return {
    controller: function($scope) {
    },
    link: function(scope, element, attrs) {
      var expression = attrs['entity'];
      scope.onetime = $parse(expression)(scope);
      $log.log('onetime');
      $log.log(scope.onetime);

      setInterval(function () {
          if (expression) {
              scope.intervaled = $parse(expression)(scope);
              scope.$apply();
              $log.log('interval');
              $log.log(scope.intervaled);
          }
      }, 2000);
    }, 
    template: '<span>{{onetime}}</span>-<span>{{intervaled}}</span>'
  };
})

And the obligatory plnkr:

http://plnkr.co/edit/2jfa1dcwguO400zRjJxU?p=preview

1 Answer 1

3

Instead of pooling just take advantage of the AngularJS $digest loop and observe the changes in the attribute:

  var entityValue = $parse(attrs.entity);

  scope.$watch(entityValue, function(newValue, oldValue){
     scope.intervaled = newValue;
  });

The $scope.$apply should be always called on the end where you know that you are outside of the AngularJS world - in this case on the sending end:

    setInterval(function() { 
      $scope.$apply(function(){
        $scope.thing = { awesome: 'cool'+count++ }  
      })
    }, 2000)

And finally the working plunk: http://plnkr.co/edit/LBwl5IeA3rXrHfTLEFMZ?p=preview

Please note that having a directive with a template that doesn't isolate a scope is playing with fire as your directive might easily override data needed by other parts of your application (intervaled in your case).

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, and special thanks for the tip about isolate scope. So in general I should use isolate scope if my directive has a template?
Yes, I would say that a good rule of thumb is this: if you've got a template that reads directive specific model (which means that you've got directive specific variables on a scope), you should isolate a scope in order to avoid potential clashes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.