具有双向绑定的隔离范围指令不反映控制器范围的变化

时间:2014-07-24 23:54:10

标签: javascript angularjs angularjs-directive

摘要:

当尝试修改已在隔离范围指令中为双向数据绑定设置的范围变量(数组)时,隔离范围指令中对变量的修改不会反映控制器范围内的更改。

玩具示例:

目前我有一个排序指令,我想在使用ng-repeat的表上定义。 ng-repeat使用ATableController控制器范围内的相同数据来创建表:

$scope.tableData = [{'col1' : 1,'col2' : 'fff'},
                             {'col1' : 2,'col2' : 'aaa'},
                             {'col1' : 3,'col2' : 'bbb'},
                             {'col1' : 4,'col2' : 'ccc'}];

我希望排序指令能够在其隔离的范围内操作相同的数据。

在指令中设置如下

... scope :
                  {
                    tableSortData        : '=',
                    tableSortRowAccessor : '=',
                    tableSortPrimer      : '='
                  },
...

在索引中称为以下

...
<body ng-controller="ATableController">
       <table table-sort table-sort-data="tableData">
...

在链接功能中,为表头分配了一个单击处理程序。单击此处理程序将触发sort函数,该函数最终运行此行代码。

scope.tableSortData = []; //which would be a sorting line in the real code

这些更改是 NOT 来自控制器内部,因此表格不会按预期更改。

这是一个vanilla js问题,(错误的引用正在制作等等)或者是我的angular指令。无论哪种方式,我做错了什么以及如何解决这个问题?

守则:

plunkr

http://plnkr.co/edit/5yxRj6?p=info

的index.html          

  <head>
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script data-require="angular.js@*" data-semver="1.2.0" src="http://code.angularjs.org/1.2.0/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-controller="ATableController">
   <table table-sort table-sort-data="tableData">
    <thead>
        <tr>
            <th>Column1</th>
            <th>Column2</th>
        </tr>

    </thead>
    <tbody>
        <tr ng-repeat="row in tableData" >
            <td>{{row.col1}}</td>
            <td>{{row.col2}}</td>
        </tr>
    </tbody>
   </table>
  </body>

</html>

的script.js

var myApp = angular.module('myApp', [])

  .controller('ATableController', function($scope)
  {
      $scope.tableData = [{'col1' : 1,'col2' : 'fff'},
                         {'col1' : 2,'col2' : 'aaa'},
                         {'col1' : 3,'col2' : 'bbb'},
                         {'col1' : 4,'col2' : 'ccc'}];

  })

  .directive('tableSort', [function()
  {
    return {
      restrict : 'A',
      replace  : false,

      scope :
      {
        tableSortData        : '=',
        tableSortRowAccessor : '=',
        tableSortPrimer      : '='
      },

      link : function(scope, element)
      {
        console.log(scope.tableSortData);

        // Await click events on header
        element.find('th').on('click.header', function(event)
        {
          var field = $(event.target).attr('field-name');
          augmentTableSortData();
        });

        function augmentTableSortData()
        {
          console.log(scope);
          console.log(scope.tableSortData);
          scope.tableSortData = [];
          console.log(scope.tableSortData);
        }

      }
    }

  }])

1 个答案:

答案 0 :(得分:4)

问题是你没有在你的点击功能中调用scope.apply:

 function augmentTableSortData()
    {
      console.log(scope);
      console.log(scope.tableSortData);
      scope.tableSortData = [];
      console.log(scope.tableSortData);
      scope.$apply();   // <------ this needs to be called because the scope data is being modified in the click function outside of angular's digest cycle.
    }

演示:http://plnkr.co/edit/as5Wek?p=preview

Documentation

  

范围提供API($ apply)以通过系统将任何模型更改传播到来自&#34; Angular领域&#34;以外的视图中。 (控制器,服务,角度事件处理程序)。