AngularJS:指令内部的双向绑定

时间:2014-03-10 14:11:01

标签: javascript angularjs angularjs-directive

我对Angularjs相对较新,我正在编写应用程序。该应用程序有一个对象数组,每个对象都有一个名为status的私有变量。我有两个过滤器,它们根据状态返回这些对象的子集。例如,对应于这两个过滤器的状态分别为“NEW”和“OLD”。

接下来,我编写了一个指令,使得由这些对象形成的div可拖动。基本上,该指令所做的是通过双向数据绑定接收对象,然后通过调用相应的方法来更改对象的状态。

问题是,对象状态的变化不会立即更新过滤器。例如,当我将三个div拖到另一半时,它们的状态会更新,但过滤器不会更新。

这是指令:

.directive('draggable', function ($document) {
return {
    scope: {
        bill: '=' // the bill object
    },
    restrict: 'A',
    link: function (scope, element, attr) {
        // do something here
        console.log('bill', scope.bill);
        var startX = 0,
            startY = 0,
            x = 0,
            y = 0,
            sourceX = 0,
            sourceY = 0,
            windowWidth = 0;

        element.on('mousedown', function (event) {
            event.preventDefault();
            startX = event.pageX - x;
            startY = event.pageY - y;
            $document.on('mousemove', mousemove);
            $document.on('mouseup', mouseup);
            windowWidth = $(window).width();
            sourceY = event.pageY;
            sourceX = event.pageX;
        });

        function mousemove(event) {
            y = event.pageY;
            x = event.pageX;
            element.css({
                top: y + 'px',
                left: x + 'px'
            });
        }

        function mouseup(event) {
            $document.unbind('mousemove', mousemove);
            $document.unbind('mouseup', mouseup);
            console.log('mouseup', startX, startY, event.screenX, event.screenY);
            var mid = windowWidth / 2;

            if (sourceX < mid && event.pageX >= mid) {
                // yes there was a change of sides
                scope.bill.markCooking(); // change the status to COOKING
                console.log('moved to COOKING', scope.bill.getStatus());
            } else if (sourceX >= mid && event.pageX < mid) {
                scope.bill.enq(); // change the status to NEW
                console.log('moved to ENQ', scope.bill.getStatus());
            }
        }
    }
}})

我在这里做错了什么?

1 个答案:

答案 0 :(得分:3)

任何时候你都在浏览器事件处理程序中,你实际上是在Angular的生命周期之外。用户的操作已触发事件,但Angular不知道它需要检查并更新其绑定(在这种情况下,是帐单状态)。

手动调用scope.$apply()会触发Angular的更改检测,并会更新绑定:

scope.$apply(function() {
  if (sourceX < mid && event.pageX >= mid) {
    // yes there was a change of sides
    scope.bill.markCooking(); // change the status to COOKING
    console.log('moved to COOKING', scope.bill.getStatus());
  } else if (sourceX >= mid && event.pageX < mid) {
    scope.bill.enq(); // change the status to NEW
    console.log('moved to ENQ', scope.bill.getStatus());
  }
});

您可以在此处详细了解范围及其生命周期:http://docs.angularjs.org/guide/scope