使用ng-model避免组件指令中的$ digest延迟

时间:2018-05-25 00:07:35

标签: angularjs angularjs-directive angularjs-ng-model angularjs-components angularjs-ng-change

如何在angularJs

中的指令中调用控制器的任何函数

我正在尝试调用父控制器的函数,当指令的绑定值发生变化时,该函数与指令没什么关系。

我一直在查看堆栈中的Q& A,但所有这些都与从指令传递给控制器​​的值有关,这不是我的情况。

我认为我的情况通常很常见,情况是: 在循环中显示复杂对象,对象的属性之一绑定在指令上。当属性发生变化时,请使用更新的复杂对象执行某些操作。

但是在我的代码中,它会打印旧的对象值而不是更新的对象值。我的猜测是在$ digest进程完成之前调用了我的更新函数。

有什么建议吗?

plunker示例:https://plnkr.co/edit/bWGxEmJjNmiKCkRZTqOp?p=preview

这是控制器代码:

  var $ctrl = this;
  $ctrl.items = [
      {id: 1, value: 10}, {id: 2, value: 20}, {id: 3, value: 30}
  ];

  $ctrl.update = function(item){
    //trying to update item after changing
    console.log("updated item is: " + angular.toJson(item));
  };

以下是指令代码:

var controller = function($scope){
   var $ctrl = this;
   $ctrl.clicked = function(){
      $ctrl.value = $ctrl.value + 1;

      //calling the bind on-change function defined in controller
      $ctrl.onChange();
   }
};

return {
   restrict: 'E',
   scope: {
          value: '=',
          onChange: '&'
   },
   controller: controller,
   controllerAs: '$ctrl',
   bindToController: true,
   templateUrl: 'directive.html'
};

和Html看起来像这样:

<div ng-repeat="item in mc.items">
  <my-directive value="item.value" on-change="mc.update(item)"></my-directive>
</div>

和指令模板:

<button type="button" ng-click="$ctrl.clicked()">{{$ctrl.value}}</button>

1 个答案:

答案 0 :(得分:0)

$digest进程完成之前调用更新函数是正确的。

一种方法是使用ng-modelng-change更新值:

<my-directive ng-model="item.value" ng-change="mc.update(item)">
</my-directive>

JS:

$ctrl.value++;
$ctrl.ngModelCtrl.$setViewValue($ctrl.value);

使用此方法,ngModelController会在调用ng-change之前更新该值。

The Demo

angular.module('myApp', [])
.controller('myController', function(){
  var $ctrl = this;
  $ctrl.items = [
      {id: 1, value: 10}, {id: 2, value: 20}, {id: 3, value: 30}
  ];

  $ctrl.update = function(item){
    //trying to update item after changing, but here it prints out old item instead of updated item.
    console.log("updated item is: " + angular.toJson(item));
  };
  
})
.directive('myDirective', function(){
    var controller = function(){
      var $ctrl = this;
      $ctrl.clicked = function(){
        $ctrl.value++;
        $ctrl.ngModelCtrl.$setViewValue($ctrl.value);
        console.log("calling clicked in directive and value is ", $ctrl.value);
      }
    };

    return {
        restrict: 'E',
        require: {ngModelCtrl: 'ngModel'},
        scope: {
          value: '<ngModel',
        },
        controller: controller,
        controllerAs: '$ctrl',
        bindToController: true,
        template: `<button type="button" ng-click="$ctrl.clicked()">
                   {{$ctrl.value}}
                   </button>`
    };
});
<script src="//unpkg.com/angular@1.6/angular.js"></script>
<body ng-app='myApp' ng-controller="myController as mc">
      <div ng-repeat="item in mc.items">
        id={{item.id}}
        <my-directive ng-model="item.value" ng-change="mc.update(item)">
        </my-directive>
      </div>
</body>

  

我不太明白这两行:

     
      
  1. require: {ngModelCtrl: 'ngModel'}。 ngModelCtrl是否可以重命名'ngModel',以便可以在指令的控制器中使用?
  2.   
  3. value: '<ngModel''<'做了什么?
  4.   

require: {ngModelCtrl: 'ngModel'}ng-model控制器API绑定到名称为ngModelCtrl的指令控制器。

scope: {value: '<ngModel'}创建ng-model属性与名称为value的控制器的单向绑定。

有关详细信息,请参阅

使用ng-model可以与ngFormController的验证API集成。可以使用多个输入创建自定义表单组件。

有关详细信息,请参阅