17
votes

I was able to see true or false and return strings in checkboxes with ng-true-value and ng-false-value, but in additional, I want to give the checkbox an integer and if it's checked, it returns an integer.

Which should be similar to when I get a value from a selectbox: http://jsfiddle.net/PuDRm/

But I can't seem to get the same idea in a checkbox: http://jsfiddle.net/PuDRm/1/

<input type="checkbox" ng-model="testc" ng-true-value="Yes" ng-false-value="No" ng-change="processtest()" /> Yes

I'm a total newbie and trying to understand AngularJS.

6
In your JSFiddle, you did not bind the select to an integer, but to the object itself. You should do ng-options="t.value as t.name for t in tests" if you want test to be only the integer and not test.value. - jpmorin
The checkbox works with strings by default, you would need a directive to parse the model value back and forth or you could use the ng-checked directive and pass a condition. - jpmorin
did not know about ng-true-value/ng-false-value, very useful - chiliNUT

6 Answers

14
votes

It sounds like you are trying to bind to two separate values with the checkbox.

In the select the view is the name you gave e.g. 'test1', and the model is the number, e.g. '1'. For the checkbox, the view is a check or a blank square and the model is Yes/No (or whatever you want to put in the ng-true-value and ng-false-value). There's no room to have it produce a number too.

It would be simpler to let the checkbox model be the default (boolean) type by omitting the ng-true-value and ng-false-value attributes. You can then display the number and text based on this like in this updated fiddle: http://jsfiddle.net/D5DGf/1/

The {{ ... }} bindings take care of updating when the function values change, so you don't need to use ng-change either.


What was wrong with the original checkbox fiddle?

In the processtest function you are taking the model (Yes/No) and changing it to always be either 8 or 1. The checkbox (in fact, ngModel) doesn't understand this as it expects to always see Yes/No. As it doesn't know what to do, it falls back to being unchecked.

This is why the checkbox in the original fiddle is uncheckable.

9
votes

If you still want to set use a number for your model and checbox value, you could do it with a custom directive to parse the string back to integer.

Demo: http://jsfiddle.net/qw5zS/

html

<input type="checkbox" ng-model="test" parse-int ng-true-value="1" ng-false-value="0" /> 

js

app.directive('parseInt', [function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, elem, attrs, controller) {
            controller.$formatters.push(function (modelValue) {
                console.log('model', modelValue, typeof modelValue);
                return '' + modelValue;
            });

            controller.$parsers.push(function (viewValue) {
                console.log('view', viewValue, typeof viewValue);
                return parseInt(viewValue,10);
            });
        }
    }
} ])

But this might not be a good practice using checkbox, you should stay with the default behavior and use a boolean, then format the view like you want, but keep your data clean.

6
votes

If you change the column in database from integer to char, it works with

<input type="checkbox" ng-model="testc" ng-true-value="1" ng-false-value="0" ng-change="processtest()" /> Yes
1
votes

Another approach without the needs of ng-model, ng-true-value and ng-false-value. Let's keep those the way they are.

js

angular.module('whateverModule')
    .directive('toggleInt', function () {
        function link ($scope, $element, attr) {
            $element.on('click', function () {
                $scope.$apply(function() {
                    $scope.toggleModel = +!$scope.toggleModel;
                });
            });

            $scope.$watch('toggleModel', function (value) {
                $element.prop('checked', !!value);
            });
        }

        return {
            restrict: 'A',
            scope: {
                toggleModel: '='
            },
            link: link
        };
    });

html

<input type="checkbox" toggle-int toggle-model="intModel">
<span>Value: {{intModel}}</span>
1
votes

Here is the solution which worked best in my trials :

<input type="checkbox"
   ng-true-value="{{ 1 | json }}" ng-false-value="{{ 0 | json }}"
   ng-model="myVariable">
0
votes

What I ended up doing was just using an if statement on the controller.

Example:

$scope.status = ($scope.status === 1 ? true : false);