手动触发自定义指令内的ngChange

时间:2016-05-24 13:55:04

标签: angularjs angularjs-directive

我想构建具有与普通输入字段相同的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

现在我想定义输入检查方法,如

function checkInput1() {
  ...
  if( <changes in input 1 are legit> ) {
    fireOuterNgChange();
  }
}
function checkInput2() {
  ...
  if( <changes in input 2 are legit> ) {
    fireOuterNgChange();
  }
}

最后我希望能够使用我的自定义指令,如:

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

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

2 个答案:

答案 0 :(得分:2)

所以在这里你需要做两件事:

  1. 拦截内部指令<input>元素的更改。
  2. 将这些更改转发给您的自定义<my-dir>的父级。
  3. 对于(1),你只需按照你的说法做:你在你的指令范围内注册回调(scope.checkInput1 = function() { ... })。

    然后,要将事件转发给父级(最后模仿<input ng-change>行为),您需要在Directive的隔离范围中声明一个表达式绑定,如下所示:

    scope: {
      onDateChange: '&'
    }
    

    在父控制器上,假设您在范围中声明了一些$scope.onDirectiveDateChange = function() { ... },您只需将回调传递到您的自定义指令中,如下所示:

    <my-dir on-date-change="onDirectiveDateChange()"></my-dir>
    

    然后你从你的指令checkInput2

    中调用它
    scope.onDateChange(); // This will call parent's "onDirectiveDateChange()" if defined
    

答案 1 :(得分:2)

@Neozaru答案很完美。但为了完整起见,我发布了一个完整的代码示例,以便于理解。在John Papa's Style Guide之后使用controllerAs语法而不是$scope(示例用例:具有可重复使用的用户表单):

使用自定义ng-change事件实现自定义指令

首先是模板

 // 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">

指令和控制器

;(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

现在我们可以将我们的指令与普通的ng-change侦听器一起使用。也许是为了注册新用户:

<password-form ng-model="the-model" ng-change="checkIfUsernameExists()">