Angular two-way-binding with sub elements

折月煮酒 提交于 2019-12-07 16:31:28

问题


my problem is with creating an angular directive.

I want to create a group of checkboxes with just one single ng-model. It's like a bitfield or flags, i.e. the checkboxes have values from 0, 1, 2, 3 up to n but for ng-model I just want to add 2^value of all checked checkboxes. The values to add are then 1, 2, 4, 8, 16, ...

I wonder if there is a better, more correct or just simpler solution to my problem.

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

In the example you can change the value in the textbox and the checks will be updated, but not the other way. It's a bit crazy, the code is working on my dev machine, but not in 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 in advance knut


回答1:


Don't bind the ng-model directly to primitive types, use an object instead:

$scope.sum = {
  ofCheckValues: 3
};

And on the HTML:

ng-model="sum.ofCheckValues"

“Whenever you have ng-model there’s gotta be a dot in there somewhere. If you don’t have a dot, you’re doing it wrong.”

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




回答2:


Found a more elegant and shorter way: http://plnkr.co/edit/9h7EkEpDohXTniIDHdc5

My problem was

  • didn't realize, that link() is called for each element
  • therefore everytime a new 'scope' is created (for each element)
  • I just have to stored a reference to the actual element in my variable (now called checkbox; was an array in the first version) for updating it, when the model changes (scope.$watch)
  • I do not need a "global" flagSum, just a lokal one in the checkbox-binding for transfering the value to scope.$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);
                });
            });
        }
      };
    });
    


来源:https://stackoverflow.com/questions/15133561/angular-two-way-binding-with-sub-elements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!