与子元素的角度双向绑定

时间:2013-02-28 10:49:54

标签: checkbox angularjs model-binding angularjs-directive

我的问题在于创建一个角度指令。

我想用一个单一的ng模型创建一组复选框。它就像一个位域或标志,即复选框的值从0,1,2,3到n,但对于ng-model,我只想添加所有选中复选框的2 ^值。要添加的值是1,2,4,8,16 ......

我想知道我的问题是否有更好,更正确或更简单的解决方案。

http://plnkr.co/edit/9h7EkEpDohXTniIDHdc5

在示例中,您可以更改文本框中的值,并且将更新检查,但不会更新。这有点疯狂,代码正在我的开发机器上工作,但不在Plnkr!

app.directive('ngCheckboxFlags', function () {
return {
    restrict: 'A',
    require: 'ngModel',
    link: function (scope, element, attrs, ctrls) {
        var flagSum;
        var checkboxes = [];

        // trigger changes of the ngModel
        scope.$watch(attrs.ngModel, function (value) {
            flagSum = value;
            for (var i = 0, ii = checkboxes.length; i < ii; ++i) {
                var checkbox = checkboxes[i];
                checkbox.checked = flagSum & (1<<checkbox.value);
            }
        });

        for (var i = 0, inputs = element.find('input[type=checkbox]'), ii = inputs.length; i < ii; ++i) 
        {
            var checkbox = inputs[i];
            checkboxes.push(checkbox);
            // trigger changes of HTML elements
            $(checkbox).bind('change', function () {
                flagSum = ctrls.$viewValue ^ (1<<this.value);
                console.log(flagSum);

                //ERROR: Change not happening, textbox shows old value
                scope.$apply(function () {
                    ctrls.$setViewValue(flagSum);
                });
            });
        }
    }
};
});
提前thnx 克努特

2 个答案:

答案 0 :(得分:5)

不要将ng-model直接绑定到基本类型,而是使用对象:

$scope.sum = {
  ofCheckValues: 3
};

在HTML上:

ng-model="sum.ofCheckValues"

“每当你拥有ng-model时,某处都会有一个点。如果你没有一个点,那你做错了。“

plunker http://plnkr.co/edit/NRAk3kyP1rdDmYrsz6ZL?p=preview

答案 1 :(得分:1)

找到一种更优雅,更短的方式:http://plnkr.co/edit/9h7EkEpDohXTniIDHdc5

我的问题是

  • 没有意识到,为每个元素调用了link()
  • 因此,每次创建新的“范围”(对于每个元素)
  • 我只需要存储对我的变量中的实际元素的引用(现在称为复选框;在第一个版本中是一个数组),以便在模型更改时更新它(范围。$ watch)
  • 我不需要“全局”flagSum,只是复选框绑定中的一个lokal,用于将值传输到范围。$ apply

    app.directive('ngCheckboxFlags', function () {
      return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ctrls) {
            var checkbox = element.find('input[type=checkbox]')[0];
            if (typeof checkbox === "undefined")
              return;
    
            // trigger changes of the ngModel
            scope.$watch(attrs.ngModel, function (value) {
                checkbox.checked = value & (1<<checkbox.value);
            });
    
            $(checkbox).bind('change',  function () {
                var flagSum = ctrls.$viewValue ^ (1<<this.value);
    
                scope.$apply(function () {
                    ctrls.$setViewValue(flagSum);
                });
            });
        }
      };
    });