简体   繁体   English

AngularJS:指令两种方式的数据绑定不起作用

[英]AngularJS : directive two way data binding not working

I have a controller with following code snippet, 我有一个带有以下代码段的控制器,

...
$scope.selected_contents = [];
$scope.$watch('selected_contents', function (sel_contents) {
  console.log(sel_contents, 'selected contents');
}, true);
...

a directive, 指令

commonDirectives.directive('chkbox', function() {
  return {
    restrict: 'A',
    require: '?ngModel',
    scope : {
        item : '=item',
        selection_pool: '=selectionPool'
    },
    link: function(scope, elem, attrs, ngModel) {
      console.log('selected contents are', scope.selection_pool);
      // watch selection_pool
      scope.$watch('selection_pool', function (pool) {
        console.log(pool, scope.selection_pool, 'pool updated');
        if (_.contains(pool, scope.item)) {
          elem.prop('checked', true);
        }
        else {
          elem.prop('checked', false);
        }
      });
      // toggle the selection of this component
      var toggle_selection = function () {
        if(_.indexOf(scope.selection_pool, scope.item) != -1) {
          scope.selection_pool = _.without(scope.selection_pool , scope.item);
        }
        else {
          scope.selection_pool.push(scope.item);
        }
      };
      elem.on('click', toggle_selection);
    }
  };
});

and a template which uses the directive, 和使用指令的模板,

<tr ng-repeat="content in contents">
      <td><input type="checkbox" selection_pool="selected_contents" item="content" chkbox></td>
</tr>

The problem is, changes in selection_pool in the directive is not reflected to selected_contents in the controller. 问题是,指令中selection_pool中的更改未反映到控制器中的selected_contents中。 What am i missing? 我想念什么?

Update 1: 更新1:

Following the suggestion from @mohamedrias I wrapped the changes in scope with scope.$apply . 按照@mohamedrias的建议,我用scope.$apply包裹了范围的变化。 Doing so updates selected_contents in controller only while adding the content but not while removing it. 这样做仅在添加内容时更新控制器中的selected_contents ,而在删除内容时不更新。

  ...
  // toggle the selection of this component
  var toggle_selection = function () {
    if(_.indexOf(scope.selection_pool, scope.item) != -1) {
      scope.$apply(function () {
        scope.selection_pool = _.without(scope.selection_pool , scope.item);
      });
    }
    else {
      scope.$apply(function () {
        scope.selection_pool.push(scope.item);
      });
    }
  };
  ...

Angular uses name-with-dashes for attribute names and camelCase for the corresponding directive name Angular使用带破折号的名称表示属性名称,使用camelCase表示相应的指令名称

From here . 这里

The variable should be changed from this selection_pool : 该变量应从以下selection_pool进行更改:

<input type="checkbox" selection_pool="selected_contents" item="content" chkbox>

to selection-pool : selection-pool

<input type="checkbox" selection-pool="selected_contents" item="content" chkbox>

And this selectionPool into the directive: 并将此selectionPool放入指令中:

scope : {
    item : '=item',
    selectionPool: '=selectionPool'
}

EDIT : Because the selectionPool is an array, you should use $watchCollection : 编辑 :因为selectionPool是一个数组,您应该使用$watchCollection

scope.$watchCollection('selectionPool', function (pool) 

And when you add/remove values from the array in toggle_selection function, should be wrapped within the $timeout function: 而且,当您在toggle_selection函数中从数组添加/删除值时,应将其包装在$timeout函数中:

$timeout(function () {
            if (_.indexOf(scope.selectionPool, scope.item) != -1) {
                scope.selectionPool = _.without(scope.selectionPool, scope.item);
             } else {
                 scope.selectionPool.push(scope.item);
             }
});

This is to assure that a digest cycle is going to be applied afterwards. 这是为了确保digest循环将在以后应用。

Here's the code working on a jsfiddle : http://jsfiddle.net/0rvcguz0/3/ 这是在jsfiddle上工作的代码: http : //jsfiddle.net/0rvcguz0/3/

After researching for entire day, I ended up here . 经过一整天的研究,我终于来到这里 If someone is having any trouble with Angularjs scope, I highly encourage to read it. 如果有人对Angularjs范围有任何Angularjs ,我强烈建议您阅读它。

The proper solution in my case was to wrap selected_contents by an object. 在我的情况下,正确的解决方案是通过对象包装selected_contents eg 例如

$scope.selected = {};
$scope.selected.contents = [];

Then in the template replace selcted_contents with selected.contents . 然后在模板selcted_contents替换为selected.contents

But still what I don't understand is, [] or an Array is also an object. 但是我仍然不明白, []还是数组也是一个对象。 My earlier code should have worked according to the information I found in the wiki. 我以前的代码应该已经按照我在Wiki中找到的信息工作了。 If anyone could explain me why I would really appreciate it :). 如果有人能解释我为什么我会非常感激:)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM