Angular.js: Feature: ngTrueValue should accept non-string values

Created on 25 Jul 2012  ·  60Comments  ·  Source: angular/angular.js

For ng-model checkboxes, ngTrueValue only supports string. It should really just accept an angular expression and eval to get the value so it supports say a js object.

PRs plz! forms moderate feature

Most helpful comment

I just had an interesting realization. What I was trying to do - and from the looks of it, what a lot of you have been trying to do - can actually be accomplished with:

ng-true-value="{{ myVariable | json }}"

This supports string values, booleans and numbers. Not sure yet whether I actually like this, but I certainly found it entertaining. And maybe this will help somebody else.

All 60 comments

I'm not entirely sure of the purpose of ngTrueValue, except that it seems like a convenience directive for adding watches to a controller for one case. I suspect that if you want to set some model to a complex value, it might be cleaner to put a $scope.$watch on your checkbox's model and modify a model on the scope accordingly.

@coli, do you have a specific use case in mind? @IgorMinar, @mhevery, @vojtajina, what do you guys think?

Use case is fairly common actually:

I have a array of say category objects in say $scope.categories=[{id:5,name:"First"},...}

Then I have a selectedCategories array that contains a subset of those categories.

I want to show a checkbox for some categories(paging), and when you check or uncheck the checkbox, selectedCategories is changed.

I actually wrote a directive that will overwrite the default checkbox behavior to add support for the above. I can share the code if needed.

My usage ended up like this, keyField was needed to do object comparison as in my case, selected group object and group object could be slightly different initially (they came from 2 different backend API)

<ng-repeat="group in groups>
    <input type='checkbox' ng-model="selectedArray" ng-true-value="group" mi-checkbox="{keyField:'id'}">
</>

Heck, I have a far simpler use case that I was disappointed to discover doesn't work - I need an integer, rather than string!

I'm using a template to render a checkbox control. In this case i cannot know the true value, that value depends on specific control information i want to render.

I too would prefer that ng-true-value be an expression. If your number of checkboxes is determined at run time you have to resort to scope methods with timeout wrappers.

+1. Support expression in ng-true-value

+1 Support integer in ng-true-value

+1 for expression instead of string

+1 Support expressions!

+1 for expressions

+1 Support objects:

<div ng-repeat="group in groups">
    <input type='checkbox' ng-model="array[$index]" ng-true-value="group" />
</div>

@coli would you mind sharing the directive you wrote? It would be a great help to me while this is issue is still being considered. Maybe in a gist?

@brab I wrote it at a previous job unfortunately, but basically, it's similar to the built in code for checkboxes, I copy/pasted into a custom directive and added expression support. (+ a ugly hack to remove the the built-in one)

Expressions would be great! However, even javascript truth testing for integers would be expected. I use $resource to populate an object that returns integer values (1 or 0) from a database boolean. These are then attached to the $scope for which the ng-model on the input is bound. Was really surprised to find out setting ng-true-value="1" would not recognize integer 1 as true and check the box. Will look into other methods mentioned in the meantime.

+1

+1 for expressions

+1. Support expression in ng-true-value

+1 on supporting expressions!
In my case, need to build a form dynamically.
Eg: http://jsfiddle.net/federosky/N8Wjm/5/

+1 for integer

1+ for integer

+1 for integer (or any JS number)

:+1: for supporting expressions please! please! pleaseeee! :-)

+1 at least for integer support, preferably expressions as well.

How about someone puts forward a PR for supporting numbers?

+1 for expressions

+1 for integer

+1 for integer

+1

:+1: for expressions.

+1. Just run into the problem when I have a boolean property 'hidden' that should be represented as 'Visible' checkbox on the page. So, I need 'checked' state to mean FALSE and unchecked to mean 'TRUE'.

I wonder what would be an easy workaround for this issue? I don't really like writing my own checkbox directive or polluting the scope with the inverse auxiliary boolean properties just in order to use them for indirect binding.

This is likely pretty trivial to implement, I'll have a go at it before bed.

My patch supports only constant expressions, but if people really need it, I suppose any expression would suffice. This was the easiest way to not cause a breaking change, though.

+1

+1

+1

+1 for integer type

+1

+1 for expressions

+1

+1

+1

+1

:+1:

These are the hacks that are required now (many WTFs):

<input type="checkbox" ng-model="fake" ng-checked="!notChecked" ng-change="notChecked = !notChecked"/>

+1

+1 it's been two years of "+1"s. Why aren't we supporting this yet?

@jancarloviray, +1

Too bad: To me this means things got more complicated.
Previously I used
ng-true-value="{{proxyOnValue}}"
where proxyOnValue was initialized in a controller.
(The same view is reused for HTTP/HTTPS/FTP/POP3/SMTP proxy configuration where the actual value is different.)

Now I tried
ng-true-value="proxyOnValue"
but that throws an exception because the expression is not constant.

So this means I have to replace a simple implementation (ngTrueValue) with a more complex implementation (watch or Object.defineProperty), so actually the opposite of what was intended.

Why this artificial restriction?
Just

  • use the current value of ngTrueValue/ngFalseValue whenever the model changes or the user clicks the checkbox
  • for good measure have an internal watch on the ngTrueValue/ngFalseValue expressions (if they are not constant) and update the checkbox state when the watch triggers.

@eekboom - you can still use your interpolation: http://plnkr.co/edit/LQ6OpFjkjiFLxxMJ9hxj?p=preview

@petebacondarwin - he can use the interpolation, but it won't help him: http://plnkr.co/edit/nNwjEkPIDJwe60HWX950?p=preview
The value is checked only once - later changes are not taken into acount, so only the initial value is used always.

@dliebscher - my understanding was that @eekboom only wanted to initialise it once:

Previously I used ng-true-value="{{proxyOnValue}}" where proxyOnValue was initialized in a controller.

Yes and no: I want to initialize it only once, but only after the proxy configuration has been loaded via xhr. So it changes (from undefined) once after the view is initialized.

@eekboom
When I was migrating from 1.2, I switched to following:

ng-true-value="{{proxyOnValue}}"

to

ng-true-value="'{{proxyOnValue}}'"

Which works, but looks dumb

I just had an interesting realization. What I was trying to do - and from the looks of it, what a lot of you have been trying to do - can actually be accomplished with:

ng-true-value="{{ myVariable | json }}"

This supports string values, booleans and numbers. Not sure yet whether I actually like this, but I certainly found it entertaining. And maybe this will help somebody else.

getu-lar i've tried what you said, with a complex object, it works. In the ng-false-value i filled with ng-false-value="{}" .Before deal with data, i pass a filter to cut off all falsy values from the array. So, many thanks!

getu-lar 's solution worked for me. Thanks.

I was trying to use an expression which resolved to a string with underscore in it, e.g. "101_3". I used getu-lar 's solution and it simply works. Feels like a hack though. Thanks for sharing it !

+1 for expressions

+1

It doesn't seem like there is much hope for Angular team to provide a sane checkbox directive for 1.x series... It can't be too difficult. Expression support would be fully backwards compatible due to the mandatory quoting.

Until then the suggested workaround is working for me:

ng-true-value="{{ myVariable | json }}"

Ensure that myVariable is defined in the controller. I tried to define it in post-link and it did not work.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

brijesh1ec picture brijesh1ec  ·  3Comments

guyandtheworld picture guyandtheworld  ·  3Comments

jtorbicki picture jtorbicki  ·  3Comments

piu picture piu  ·  3Comments

ashclarke picture ashclarke  ·  3Comments