Reputation: 20053
Somehow, through the magic of Angular, if you use ng-model
and provide it a boolean, your checkbox will be checked if said boolean is true, and unchecked if false.
<input type="checkbox" ng-model="video.hidden">
While this alone is fairly baffling, I'm actually trying to reverse the checked state, because unlike the todo example where todo.done
means the box gets checked, my model is more like todo.incomplete
.
Unfortunately my first guess didn't work:
<input type="checkbox" ng-model="!video.hidden">
I'm in a position where the model has been dictated to me, so I can't change it and don't want to have to massage it on the client (because I'm sending client objects back to the server, since it's running in a trusted environment).
Update
This works in 1.3 and doesn't give you strings (1.2.xxx gave you strings instead of booleans):
<input type="checkbox" ng-model="video.hidden" ng-true-value="false" ng-false-value="true">
Upvotes: 70
Views: 41493
Reputation: 21
My Solution is Very simple: Just use ng-true-value / ng-false-value and set false to ng-true-value and true to ng-false-value which will reverse the functionality.
<input type="checkbox" ng-model="<<-- Your Model -->> " ng-true-value="false"
ng-false-value="true">
Upvotes: 2
Reputation: 186
I think the simplest solution to get the checked or unchecked value for a checkbox is by adding the ng-init directive inside the checkbox input element as follows:
<input type="checkbox" ng-init="video = false" ng-model="video" >
This enables the initial value of the checkbox to be false, were the state is unchecked. On submitting the form, if the checkbox is unchecked the value that returns (or console) will be false, instead of 'undefined', else upon checking it will be true.
if you want to add custom made values for the true or false state, you can use:
ng-true-value="'custom_true value'"
and
ng-false-value="'custom_false value'"
inside the input element. like :
<input type="checkbox" ng-init="video = false" ng-model="video" ng-true-value="'custom_true value'" ng-false-value="'custom_false value'">
Upvotes: 0
Reputation: 3209
You can make that now without a need of custom directive, angular support ng-true-value
and ng-false-value
https://docs.angularjs.org/api/ng/input/input[checkbox]
your example should work now
<input type="checkbox" ng-model="video.hidden" ng-true-value="false" ng-false-value="true">
Upvotes: 83
Reputation: 28090
I don't think there's a way to do this purely in the template. The most obvious way to accomplish this is create a new scope variable that's manually double-bound to your model value. So like:
<input type="checkbox" ng-model="videoShowing">
And in your controller:
$scope.videoShowing = !$scope.video.hidden;
$scope.$watch('video.hidden', function(value) {
$scope.videoShowing = !value;
});
$scope.$watch('videoShowing', function(value) {
$scope.video.hidden = !value;
}
You could almost just use one-way binding with an ng-change, but that doesn't quite work:
<input type="checkbox" ng-checked="!video.hidden" ng-change="???">
Because ng-change doesn't mix the current value into the local scope at all. If you were in a context where you had access to the NgModelController you could do something, but you'd need a custom directive for that. Wouldn't be hard to make an "inverted" attribute directive that modifies the NgModel's formatters and parsers. I'd suggest that if you need lots of inverted checkboxes.
Edit
For posterity, making an "inverted" attribute is super simple, might as well just do that. Making directives always seems like a pain at first, but it really is the Angular way.
someModule.directive('inverted', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
ngModel.$parsers.push(function(val) { return !val; });
ngModel.$formatters.push(function(val) { return !val; });
}
};
});
Might need to set the priority too, or "unshift" instead of push, to make sure these guys run after the built-in inputDirective ones.
Upvotes: 23
Reputation: 5802
My solution uses a directive "negate", that you just add to the "input". It's simple, and there is no need to change the controller.
angular
.module("<< your module >>")
.directive('negate', [
function () {
return {
require: 'ngModel',
link: function (scope, element, attribute, ngModelController) {
ngModelController.$isEmpty = function(value) {
return !!value;
};
ngModelController.$formatters.unshift(function (value) {
return !value;
});
ngModelController.$parsers.unshift(function (value) {
return !value;
});
}
};
}
]
);
Use it like this:
<input type="checkbox" negate ng-model="entity.nologin">
Upvotes: 5
Reputation: 42031
This seems to work
<input type="checkbox"
ng-init = "video.checked = !video.hidden"
ng-model ="video.checked"
ng-change ="video.hidden = !video.checked"/>
It introduces a video.checked
property that's the opposite of video.hidden
and as soon as the checkbox changes the values are updated.
Example here: http://plnkr.co/edit/7HYht6ubkUUJQ0r3g16m?p=preview
Upvotes: 14