将DOM事件添加到Angular指令

时间:2014-11-03 15:53:29

标签: javascript angularjs dom-events

我想将DOM事件附加到指令元素,以便更新范围属性。不幸的是,我找不到一个“干净”的方法来做到这一点。我现在能够使用它的唯一方法是在处理程序中显式调用$apply()。我知道这是不好的做法,但它也阻止我与本机角度指令共享此代码,例如使用ng-click="myDOMEventHandler()"(因为它会触发$apply already in progress异常。

有没有办法将DOM事件添加到指令元素,以便获取对范围的更改,但无需调用$apply()

这是我的意思的一个简单例子。 You can edit this Plunker as well)。

angular.module('myApp', [])
.directive('myDirective', function ($compile) {
  return {
    link: function (scope, element) {
      scope.keystrokes = 0;

      var report = angular.element('<div ng-click="increment()">keystrokes: {{keystrokes}}</div>');
      element.after(report);
      $compile(report)(scope);

      scope.increment = function () {
        scope.keystrokes += 1;
        scope.$apply();
      };

      element.on('keyup', scope.increment);
    }
  };
});

如果在输入中输入了一些文本,则计数器会递增。如果单击该按钮,计数器也会递增 - 但如果引发$apply already in progress异常。

如果删除scope.$apply(),则异常消失,范围属性确实发生变化,但这些更改永远不会显示。

1 个答案:

答案 0 :(得分:1)

您不必使用范围。$ apply在scope.increment函数内,但您应该使用

当您在角度范围之外绑定事件时,$apply内的

element.on('keyup'...))

angular.module('myApp', [])
.directive('myDirective', function ($compile) {
  return {
    link: function (scope, element) {
      scope.keystrokes = 0;

      var report = angular.element('<div>keystrokes and clicks: {{keystrokes}} <button ng-click="increment()">Or click me</button></div>');
      element.after(report);
      $compile(report)(scope);

      scope.increment = function () {
        scope.keystrokes += 1;
      
      };
      
      element.on('keyup', function(){
        
        scope.$apply(function(){
          
          scope.increment();
          
        });
        
        
      });
    }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="myApp">
  <input my-directive="" />
</body>