Angular.js: ng-required validation not working properly with true/false radio values.

Created on 6 May 2013  路  9Comments  路  Source: angular/angular.js

See Fiddle.

I have a use case where radio input data is stored server-side as booleans - true for "yes", false for "no".

If I use value="true" and value="false" on my form, the radio control corresponding to the default value is not selected when the page loads (validation, however, works as expected).

If I use ng-value="true" and ng-value="false" instead, the default value is selected automatically based on the model as expected, but validation doesn't work correctly. The form is only declared valid if "Yes" is selected, but still invalid if "No" is selected.

I can't select "no" by default because the business rules say that the inputs should initially be unselected (presumably so the user has to actually go through the whole form and answer the questions instead of just skipping ahead because an option has already been selected for them).

PRs plz! forms moderate investigation bug

Most helpful comment

I have the same problem here. Also the model value of my second radio button (ng-value="false") is undefined instead of false, if I use ng-required.

<input type="radio" ng-required="true" ng-model="test" ng-value="true" />
<input type="radio" ng-required="true" ng-model="test" ng-value="false" />

All 9 comments

I have the same problem here. Also the model value of my second radio button (ng-value="false") is undefined instead of false, if I use ng-required.

<input type="radio" ng-required="true" ng-model="test" ng-value="true" />
<input type="radio" ng-required="true" ng-model="test" ng-value="false" />

@kpko I ended up writing my own directive to work around it. Feel free to use it! https://github.com/michaelmoussa/ng-boolean-radio

Yes, this is a corner-case. The issue is due to this check:
https://github.com/angular/angular.js/blob/e1fe2ac2691e319473ed2bbca501fc6b641024e5/src/ng/directive/input.js#L1226

that was introduced to cater for a check-box use-case:
https://github.com/angular/angular.js/blob/e1fe2ac2691e319473ed2bbca501fc6b641024e5/test/ng/directive/inputSpec.js#L906-L916

I'm afraid that I don't know what is the best course of action here :-(

The real question is this: should a false value be considered as fulfilling the required condition....

The real question is this: should a false value be considered as fulfilling the required condition....

I believe it should. In a "yes/no" scenario with no default option selected, it makes sense to map a "no" selection to false.

IMO, checking for null would be the best way to determine that the user has not fulfilled a required condition.

:+1: I agree with @michaelmoussa on this. We have a Yes/No <select> mapped to true/false values. If we make it required, the "No" cannot be selected.

In my opinion it's very well known that null is the absence of value, whereas false is an actual value. And that would make sense to consider only null instead of false if a value is required.

Now, for the checkbox use-case mentioned, I guess it may also make sense. Couldn't we make a special case for checkbox only ? Something along the lines of:

if (attr.required && (isEmpty(value) || (attr.type = "checkbox" && value === false))) {

arrrgh, spent way too much time trying to figure out why my form was throwing required. YES, false should be considered as fulfilling the required condition otherwise it makes our model/view extremely confusing.

@michaelmoussa solution works for me. Please, please pretty please use it!

I agree with @PowerKiKi - we should make the checkbox input a special case but that we shouldn't put the burden of this special case on the required directive.

We should change the normal required directive to check only for empty/null/undefined but then change the checkboxInputType directive add in an extra validator that checks for false.

I think this was fixed by the commits mentioned above, except for setting the initial checked attribute if the model is set to boolean when the input is compiled, and value is used instead of ng-value. I am going to raise this as a separate issue.

Was this page helpful?
0 / 5 - 0 ratings