AngularJS: Reverse Checkbox State

Angularjs

Angularjs Problem Overview


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">

Angularjs Solutions


Solution 1 - Angularjs

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">

Solution 2 - Angularjs

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.

Solution 3 - Angularjs

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

Solution 4 - Angularjs

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">

Solution 5 - Angularjs

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">

Solution 6 - Angularjs

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'">

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLangdonView Question on Stackoverflow
Solution 1 - AngularjsMahmoud FelfelView Answer on Stackoverflow
Solution 2 - AngularjsjpsimonsView Answer on Stackoverflow
Solution 3 - AngularjsjaimeView Answer on Stackoverflow
Solution 4 - AngularjsStephen FriedrichView Answer on Stackoverflow
Solution 5 - AngularjsAwais JamilView Answer on Stackoverflow
Solution 6 - AngularjsJEEVAN GEORGE ANTONYView Answer on Stackoverflow