AngularJS ng-change在从指令编译后不会触发

时间:2015-07-16 16:57:33

标签: javascript angularjs angularjs-directive

这是我的指示:

directive('test', ['$compile', function ($compile) {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                element.attr('ng-change', "someFunction()"); // <--- Doesnt Work
                element.attr('ng-blur', "someFunction()"); // <--- Works
                element.removeAttr('test');
                $compile(element)(scope);
            }
        };
    }])

Marup就是这个

<input ng-model="foo" test />

现在,正在调用blur处理程序,而change处理程序不是。为什么呢?

1 个答案:

答案 0 :(得分:2)

编辑: 问题已修改,现在包含ng-model,因此我删除了ngChange要求{{ngModel的原始答案1}}。现在,双重编译(以前称为&#34;非主题&#34;)是理解该问题的核心。

重要的是要认识到您正在采用的方法会导致对此元素的其他指令进行双重编译。具体而言,以下指令是有意义的:

  • ngModel - 已编译/关联两次
  • input - 已编译/关联两次
  • ngChange - 已编译/关联一次

<强> TL; DR

ngChange不会触发处理程序,因为它运行时会认为该值没有改变,因为该值之前已更改(现在等于{的值) {1}}元素)由第一次编译产生的<input>的第一个实例。

更长的版本:

ngModel指令的每个编译过程都会生成ngModel的新实例。需要ngModelController的{​​{1}}指令的每个编译传递在其input函数中获取ngModel的不同实例,并且ngModelController函数运行时它设置一个监听器来响应link元素的变化。

但是,

link仅在第二个 <input>指令实例的ngChange数组中注册一次。

因此,当第一个 ngModel.$viewChangeListeners指令的监听器通知ngModel第一个实例时(通过input } ngChange` listener。

但是当第一个 ngModelController指令实例将ngModel.$setViewValue), that instance doesn't have the设置为ngModel元素中的值时,处理其所有$viewValue<input>$parsers第二 $validators的{​​{1}}处理程序也将$viewChangeListerners设置为$watch的{​​{1}} } element。

然后,当最终第二个 ngModel指令侦听器运行时,它会将$viewValue与基础<input>元素进行比较 - 它们是现在平等 - 并跳过input / $viewValue / <input>的整个渠道。

$parsers没有使用$validators,因此它会直接侦听事件,从而触发(两次)。

<强>解决方案:

所以,小心双重编译。最小化这一点 - 并且绝对避免$viewChangeListeners / ng-blur指令的双重编译 - 的一种方法是使用ngModel和高于1的优先级。您可以将优先级任意提高到&#34;捕获&#34;元素上可能存在的其他指令:

ngModel