Angularjs 手动从自定义指令内部触发ngChange

Angularjs 手动从自定义指令内部触发ngChange,angularjs,angularjs-directive,Angularjs,Angularjs Directive,我想构建与普通输入字段具有相同ng change语法的自定义指令。假设我有这样一个指令: ;(function() { 'use strict'; angular.module('myMod', []); angular.module('myMod').directive('myDir', myDirDirective); function myDirDirective() { return { restrict: 'E', template:

我想构建与普通输入字段具有相同ng change语法的自定义指令。假设我有这样一个指令:

;(function() {
  'use strict';
  angular.module('myMod', []);
  angular.module('myMod').directive('myDir', myDirDirective);

  function myDirDirective() {
    return {
      restrict: 'E',
      template: '
        <input ng-change="checkInput1()" type=...>
        <input ng-change="checkInput2()" type=...>
      ',
      controllerAs: 'myDirDirective',
      controller: myDirController,
      require: 'ngModel',
      scope: {},
      bindToController: {
        model: '='
      }
    };
  }

// Controller goes here...

})(); // EOF
;(功能(){
"严格使用",;
角度模块('myMod',[]);
角度.module('myMod')。指令('myDir',mydirdirdirdirective);
函数myDirDirective(){
返回{
限制:'E',
模板:'
',
controllerAs:“myDirDirective”,
控制器:myDirController,
要求:'ngModel',
作用域:{},
bindToController:{
型号:'='
}
};
}
//控制器在这里。。。
})(); // EOF
现在我想定义输入检查方法,如

function checkInput1() {
  ...
  if( <changes in input 1 are legit> ) {
    fireOuterNgChange();
  }
}
function checkInput2() {
  ...
  if( <changes in input 2 are legit> ) {
    fireOuterNgChange();
  }
}
函数checkInput1(){
...
如果(){
fireOuterNgChange();
}
}
函数checkInput2(){
...
如果(){
fireOuterNgChange();
}
}
最后,我希望能够使用自定义指令,如:

<myDir ng-change="doSomethingAfterSomethingChanged()">
  ...
</myDir>

...

一个简单的用例是一个时间选择器,它有几个小时:分钟:秒:毫秒的输入字段。举个例子。我尝试了不同的方法,但没有成功;我如何才能做到这一点?

因此,在这里您需要执行两件事情:

  • 拦截内部指令
    元素上的更改
  • 将这些更改转发给自定义的父级
  • 对于(1),您只需按照您所说的操作:在指令的作用域(
    scope.checkInput1=function(){…}
    )中注册回调

    然后,要将事件转发给父级(最终模仿
    行为),您需要在指令的独立作用域中声明一个表达式绑定,如下所示:

    scope: {
      onDateChange: '&'
    }
    
    <my-dir on-date-change="onDirectiveDateChange()"></my-dir>
    
    在父控制器上,假设您在范围中声明了一些
    $scope.ondirectivedTechRange=function(){…}
    ,您只需将回调传递到自定义指令中,如下所示:

    scope: {
      onDateChange: '&'
    }
    
    <my-dir on-date-change="onDirectiveDateChange()"></my-dir>
    

    因此,这里您需要执行两件事情:

  • 拦截内部指令
    元素上的更改
  • 将这些更改转发给自定义的父级
  • 对于(1),您只需按照您所说的操作:在指令的作用域(
    scope.checkInput1=function(){…}
    )中注册回调

    然后,要将事件转发给父级(最终模仿
    行为),您需要在指令的独立作用域中声明一个表达式绑定,如下所示:

    scope: {
      onDateChange: '&'
    }
    
    <my-dir on-date-change="onDirectiveDateChange()"></my-dir>
    
    在父控制器上,假设您在范围中声明了一些
    $scope.ondirectivedTechRange=function(){…}
    ,您只需将回调传递到自定义指令中,如下所示:

    scope: {
      onDateChange: '&'
    }
    
    <my-dir on-date-change="onDirectiveDateChange()"></my-dir>
    

    @Neozaru的答案非常完美。但为了完整起见,我发布了一个完整的代码示例,以便于理解。遵循并使用
    controllerAs
    语法,而不是
    $scope
    (示例用例:具有可重用的用户表单):

    使用自定义ng更改事件执行自定义指令

    首先,模板

     // my-dir-template.html
     Username: <input type="text" name="username" ng-change="passwordForm.changeHandler()" ng-model="passwordForm.model">
     Password: <input type="text" name="password" ng-change="passwordForm.changeHandler()" ng-model="passwordForm.model">
    
    //my-dir-template.html
    用户名:
    密码:
    
    指令和控制器

    ;(function() {
      'use strict';
      angular.module('myMod', []);
      angular.module('myMod').directive('passwordForm', passwordFormDirective);
    
      function passwordFormDirective() {
        return {
          restrict: 'E',
          templateUrl: 'password-form.html',
          controllerAs: 'passwordForm',
          controller: passwordFormController,
          require: 'ngModel',
          scope: {},
          bindToController: {
            model: '=',
            ngChange: '&'                  // << bind ng-change to controller (not scope)
          }
        };
      }
    
      function passwordFormController() {  // no scope injected
        // Pseudo this
        var vm = this;
        // implement controller
        vm.changeHandler = changeHandler ;
    
    
        // // // Method implementations
        ...
        function changeHandler() {
          // we could do validation here, altough I'm not sure if this would be a good idea here. 
          // for now, we only do the change listener notification
          if(vm.ngChange === 'function') {
             vm.ngChange();
          }
        }
      }
    })(); // EOF
    
    ;(功能(){
    "严格使用",;
    角度模块('myMod',[]);
    角度.module('myMod').directive('passwordForm',passwordFormDirective);
    函数passwordFormDirective(){
    返回{
    限制:'E',
    templateUrl:'password form.html',
    controllerAs:'passwordForm',
    控制器:passwordFormController,
    要求:'ngModel',
    作用域:{},
    bindToController:{
    型号:'=',
    
    ngChange:'&'/@Neozaru answer工作得很完美。但为了完整起见,我发布了一个完整的代码示例,以便于理解。遵循并使用
    controllerAs
    语法,而不是
    $scope
    (示例用例:具有可重用的用户表单):

    使用自定义ng更改事件执行自定义指令

    首先,模板

     // my-dir-template.html
     Username: <input type="text" name="username" ng-change="passwordForm.changeHandler()" ng-model="passwordForm.model">
     Password: <input type="text" name="password" ng-change="passwordForm.changeHandler()" ng-model="passwordForm.model">
    
    //my-dir-template.html
    用户名:
    密码:
    
    指令和控制器

    ;(function() {
      'use strict';
      angular.module('myMod', []);
      angular.module('myMod').directive('passwordForm', passwordFormDirective);
    
      function passwordFormDirective() {
        return {
          restrict: 'E',
          templateUrl: 'password-form.html',
          controllerAs: 'passwordForm',
          controller: passwordFormController,
          require: 'ngModel',
          scope: {},
          bindToController: {
            model: '=',
            ngChange: '&'                  // << bind ng-change to controller (not scope)
          }
        };
      }
    
      function passwordFormController() {  // no scope injected
        // Pseudo this
        var vm = this;
        // implement controller
        vm.changeHandler = changeHandler ;
    
    
        // // // Method implementations
        ...
        function changeHandler() {
          // we could do validation here, altough I'm not sure if this would be a good idea here. 
          // for now, we only do the change listener notification
          if(vm.ngChange === 'function') {
             vm.ngChange();
          }
        }
      }
    })(); // EOF
    
    ;(函数(){
    "严格使用",;
    角度模块('myMod',[]);
    角度.module('myMod').directive('passwordForm',passwordFormDirective);
    函数passwordFormDirective(){
    返回{
    限制:'E',
    templateUrl:'password form.html',
    controllerAs:'passwordForm',
    控制器:passwordFormController,
    要求:'ngModel',
    作用域:{},
    bindToController:{
    型号:'=',
    
    ngChange:'&'//您确定您要查找的内容不能通过自定义验证器获得吗?默认情况下,通过验证将触发ngChange,不通过将停止它。不,自定义验证不是我要查找的(尽管它看起来确实像)。更多的是关于更改侦听器的问题。您确定您要查找的内容不能通过自定义验证程序获得吗?默认情况下,通过验证将触发ngChange,而不通过验证将停止它。不,自定义验证不是我要找的(尽管看起来确实如此)。这更多的是关于更改侦听器的问题。这很有效,谢谢。尽管我们尝试不使用范围(跟随John Papa:)。我将发布一个完整的代码示例,这样每个人都可以使用它…这很有效,谢谢。尽管我们尝试不使用范围(跟随John Papa:)。我将发布一个完整的代码示例,这样每个人都可以使用它。。。