为什么交易AngularJS款的D3事件对绑定没有影响?

Why D3 events that deal AngularJS models does not have effect in binding?

考虑以下 Angular JS (1.5.8) 的控制器。该项目还使用 WebCola 3.1.3 和 d3 3.4.11。

当我尝试从 d3 回调处理函数内部更改我的 $scope 的任何 属性 时,绑定在呈现的 HTML 中不起作用。

我怎样才能弄清楚如何防止 d3 的这种行为并让 2-way 绑定正常流动?

<div ng-controller="MainController">
    <h2>{{balls[0].a}}</h2>
    <button ng-click="foo()">Do it!</button>
</div>

angular.module('nua').controller('MainController', ['$scope'], function ($scope) {

    $scope.balls = [];

    $scope.onCircleClickHandler = function (data, index) {

        $scope.balls[index].a = 2;

        // The problem is here!
        // Every function of d3 that change the value
        // of any scope property takes no effect in binding

        // No one of my tries to change the value of any 
        // property of $scope.balls to see the rendered result
        // in the <h2> takes effect.

        // The value of $scope.balls[index].a is really
        // updated to "2", but the values of <h2> remains "1".

        // The calling from D3 seems to prevent something that affects binding.

    };

    $scope.foo = function () {

        $scope.balls[1].d = 5;

        // This works properly.

        // If I call onCircleClickHandler and THEN call foo,
        // then the binding takes effect and <h2> has now the 
        // "2" as innerHTML

    };

    $scope.init = function () {

        // var mycola = cola.d3adaptor() ...

        // var svg = d3.select('id') ...

        // var nodes = svg.selectAll('circle') ...

        nodes.on('click', function (data, index) {

            this.onCircleClickHandler(data, index);

        }.bind($scope))

        $scope.balls = [
            {a:1, b:2, c:3},
            {d:4, e:5, f:6}
        ];

    };


});

原因是当您从 d3 事件更新值时,angular 永远不会知道范围数据已更改,因此它需要调用摘要周期。

所以应该是这样的:

 $scope.onCircleClickHandler = function (data, index) {
        //this will notify angular that the scope value has changed.
        $scope.$apply(function () {
            $scope.balls[index].a = 2;
        });

    };