问题
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