如何在angularjs指令中观察属性?

时间:2022-11-26 22:57:06

In my attempts at having angularjs and d3js working together smoothly, I run in trouble when I try to watch an attribute value right within a directive. Let me illustrate with those two simple directives:

在我试图让angularjs和d3js顺利协同工作时,当我尝试在指令中查看属性值时,我遇到了麻烦。让我用这两个简单的指令来说明:

.directive('attr1', function($compile) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      var attr3val = 0;
      d3.select(element[0])
        .attr('attr2', true)
        .attr('attr3', attr3val)
        .on('click', function() {
          d3.select(element[0])
            .attr('attr3', function() {
              attr3val++;
              console.log("new attr3 value is", attr3val);
              return attr3val;
            });
        });

      element.removeAttr("attr1");
      $compile(element)(scope);
    }
  };
})

.directive('attr2', function() {
  return {
    restrict: 'A',
    scope: {
      attr3: "=attr3"
    },
    link: function(scope, element, attrs) {
      scope.$watch('attr3', function() {
        console.log('attr3 modification trigger');
      });
    }
  };
});

They are shown in action here - console logs have to be activated to understand clearly what happens.

它们在此处显示 - 必须激活控制台日志才能清楚地了解发生的情况。

Following this thread, I use $compile so that the attr2 directive is effectively bound after the DOM is modified by d3 calls. I then would like to watch the changes of another attribute (attr3 here). Using a private scope in attr2, I thought this to be possible, but I must be doing something wrong, as clicks in the blue square do indeed update the attribute value, but without the watch being triggered.

在这个线程之后,我使用$ compile,以便在d3调用修改DOM之后有效地绑定attr2指令。然后我想看另一个属性的变化(这里是attr3)。在attr2中使用私有作用域,我认为这是可能的,但我必须做错了,因为蓝色方块中的点击确实更新了属性值,但没有触发监视。

Maybe DOM attributes are not "watchable"? Are the only viable solutions those prescribed here?

也许DOM属性不是“可观看的”?这是唯一可行的解​​决方案吗?

Thanks by advance for your keen help!

感谢您提前寻求帮助!

EDIT

The solution using $broadcast shown hereunder is working strictly speaking, but is ineffective if the attribute is common to many elements, and I want to watch one specifically. I'm thus going for a $watch on a function evaluation that uses jQuery, as shown here.

使用下面显示的$ broadcast的解决方案严格来说,但如果该属性对于许多元素是通用的,则无效,我想特别注意一个。因此,我要在使用jQuery的函数评估中观察,如此处所示。

2 个解决方案

#1


1  

If you want to $watch an attribute, you can use $observe:

如果你想$ watch一个属性,你可以使用$ observe:

link: function(scope, element, attrs) {
  attrs.$observe('attr3', function(newValue) {
    console.log('attr3 is ', newValue);
  });
}

#2


1  

One way to solve this problem is to create custom scope events via $broadcast() within your directives and then attach a listener to the receiving directive.

解决此问题的一种方法是在指令中通过$ broadcast()创建自定义范围事件,然后将侦听器附加到接收指令。

PLUNKER

PLUNKER

e.g.

例如

.directive('attr1', function($compile) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      var attr3val = 0;
      d3.select(element[0])
        .attr('attr2', true)
        .attr('attr3', attr3val++)
        .on('click', function() {
          d3.select(element[0])
            .attr('attr3', attr3val++);
            scope.$broadcast('attr3-change', attr3val);
        });

      element.removeAttr("attr1");
      $compile(element)(scope);

      scope.$broadcast('attr3-change', attr3val);
    }
  };
})

.directive('attr2', function() {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {

      scope.$on('attr3-change', function(event, args) {
        console.log(args);
      })

    }
  };
});

#1


1  

If you want to $watch an attribute, you can use $observe:

如果你想$ watch一个属性,你可以使用$ observe:

link: function(scope, element, attrs) {
  attrs.$observe('attr3', function(newValue) {
    console.log('attr3 is ', newValue);
  });
}

#2


1  

One way to solve this problem is to create custom scope events via $broadcast() within your directives and then attach a listener to the receiving directive.

解决此问题的一种方法是在指令中通过$ broadcast()创建自定义范围事件,然后将侦听器附加到接收指令。

PLUNKER

PLUNKER

e.g.

例如

.directive('attr1', function($compile) {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {
      var attr3val = 0;
      d3.select(element[0])
        .attr('attr2', true)
        .attr('attr3', attr3val++)
        .on('click', function() {
          d3.select(element[0])
            .attr('attr3', attr3val++);
            scope.$broadcast('attr3-change', attr3val);
        });

      element.removeAttr("attr1");
      $compile(element)(scope);

      scope.$broadcast('attr3-change', attr3val);
    }
  };
})

.directive('attr2', function() {
  return {
    restrict: 'A',
    link: function(scope, element, attrs) {

      scope.$on('attr3-change', function(event, args) {
        console.log(args);
      })

    }
  };
});