控制器和外部指令之间的双向数据绑定

时间:2013-12-05 23:13:51

标签: javascript angularjs data-binding angularjs-directive angularjs-scope

我的设置:

想象一下购物车的控制器

app.controller('CartCtrl', function ($scope) {
    $scope.data = [
        {
            id:0,
            title:'article1'
        },
        {
            id:1,
            title:'article2'
        }
    ];

    $scope.countItems = function(){
        var num = 0;
        for(var i in $scope.data){
            num++
        }
        return num;
    } 
});

它在页面的某处使用:

<ul ng-controller="CartCtrl">
    <li ng-repeat="item in data">{{item.title}}</li>
</ul>

其他地方我想显示购物车中的商品数量:

<div cart-item-number>{{countItems()}}</div>

要连接数据,请使用指令

app.directive('cartItemNumber', function() {
    return {
        restrict: 'A',
        controller: 'CartCtrl'
    };
});

我的问题:

在页面加载时显示正确的数字。但是,如果我从数据对象中删除或添加项目,则 cart-item-number不会更新

如何解决此问题?

2 个答案:

答案 0 :(得分:2)

所以ng-controller="CartCtrl"controller: 'CartCtrl'是两个不同的对象。在指令声明中,您为指令指定控制器。当您的应用程序启动时,它们都会使用相同的数据进行初始化,因此似乎可以始终如一地工作。

如果你想显示CartCtrl范围内的项目数量而不是你不需要使用指令(顺便说一下,最好只使用data.length)。如果您打算将其显示在范围之外,则必须创建某种形式的通信。 或者至少在范围的层次结构中将cart移到更高的位置 - 当然,$rootScope它会在您的应用程序中随处可见(除非您使用的是isolated scope)。

答案 1 :(得分:2)

首先,原因是因为您没有在同一范围内工作。请考虑以下示例:

<body>
  <ul ng-controller="CartCtrl">
    <li ng-repeat="item in data">{{item.title}}</li>
  </ul>
  <div cart-item-number>{{countItems()}}</div>
</body>

该指令在RootScope上注册,而ngController是子范围。因此,您最终会有两个数据副本。我建议您使用AngularJS Batarang Chrome插件来显示上述范围和模型。

将上述示例中的ng-controller移动到body,您将看到预期的行为。

然而,您使用控制器的方式被认为是不好的做法。指令控制器的唯一目的是将API暴露给其他指令,用于指令通信的指令。其中“普通”控制器(在ngController和路由中使用)用于扩充范围并向范围对象添加行为。

如果需要在“普通”控制器和指令之间进行通信,则应使用中介服务(让控制器和指令都依赖于此服务),或使用$ scope事件,如$ scope。$ broadcast和$ scope。$ emit在它们之间进行通信。这将控制器与指令分离,并允许可重复使用的组件和简单的测试。