Unchecked checkbox values

Working with form check boxes can be a bit of a pain on sites with dynamic content. Saving the checked data is easy, but how do you easily save the unchecked value without manually adding it to an array from inside your code? Keep reading.

revealCMS is working great – I’m really starting to see a lot of its strengths (and, admittedly, some weaknesses) as I use it more and begin extending it. Due to how data is saved to the database, the HTML checkboxes were a bit of a problem when trying to save their unchecked state. Typically I save the post data to the object, where it is filtered and scrubbed, as necessary.Only the posted values get updated in their respective rows (makes sense, right?).

The problem is that unless a box is checked, it’s not going to be sent with the form – a problem if you have a checked box, but want to save the unchecked state.The first option is easy and probably the first solution you’d think of – write a couple lines of code for every single checkbox and set it to some default value if it’s left unchecked when the form is posted. Fine, but that takes more thinking than I want to do for something so simple, and it’s somewhat prone to error. Instead…

…the solution: Insert a hidden form field with the same name as the checkbox and the default value right before the place where the checkbox is located:
<input type="hidden" name="box1" value="0" /> <input type="checkbox" name="box1" value="1" />
What happens here is that when the checkbox is left unchecked, the hidden field’s value gets submitted, as-is. When the check box is checked, the hidden field’s POST value gets overwritten by the activated checkbox’s.
Unactivated: Hidden field’s value.
Activated: Check box’s value.

Told you it was easy!




121 Comments

> hidden field’s POST value gets overwritten by the activated checkbox’s

This is not correct. Both values will get submitted, HTML allows mutliple values with the same name. That is you’ll get something like:
process.html?box1=0&box1=1 — checked
process.html?box1=0 — unchecked

now it may work for you, but your server side code must be prepared to handle multiple values for the same variable, but saying that it “gets overwritten” is incorrect.

Hi!
I actually have exactly that problem! Is it possible to have the form giving out just “0” if it remains unchecked? And not “0, 1” !
Thank you very much for your help.

gligeti,

you’re right, technically both do get posted, however by the time it gets to your server-side script you’re likely only going to see the latter valeu = the 1. In PHP $_POST[‘box1’] would output a 1.

Let’s keep the discussion going – if there’s a better solution, please, please, please post it! It can only help us all out!

Ed,

That’s a tougher one to work-around. I’d be more likely to us javascript to change some of the values and field names. It would be a little bit tricky, and it depends on how your HTML is set-up to display previously-saved data (if any).

Another way, a much messier way, is to write server-side code that will hopefully figure-out how to pick the right value. It could work, but depending on the form and your code, may not be worth the additional effort.

If you know what you are expecting your POSTed data to be, which you should as you made the HTML form, then just create a new array from the POSTed one.

You need to name the keys of the checkbox name array:
EG

When the form is posted, make a new array using ALL the key names you KNOW are used in the checkbox names

Then use that new array to loop all keys. With each loop, check if the current key from your new array matches a key in the posted array.
If no match then that key value is NO, if it is matched then that key value is YES.
It’s IMPORTANT when you make the new array to make the keys in the same order as they appear in the html form or the loop wont match them in order and wont work correctly

Here is the full script

form.html page

eat fruit
eat bread
eat apples

post.php page

//get check boxes user DID tick
$post_array = $_POST[‘eat’];

//make new array
$array_keys = array(“fruit” => “”, “bread” => “”, “apples” => “”);

//loop through new array, if key is matched then value is yes
//else value is no

foreach ($array_keys as $key => $value){
if (array_key_exists($key, $post_array)){
$new_array[$key]=”yes”;
}else{
$new_array[$key]=”no”;
}
}

Your $new_array is now all the values submited fom tickboxes from the form, with the same key names, and for each one the user didnt tick the key is added and a value of “no” inserted.
This makes it simple to insert into a db where user settings is a yes or no
you can of course change what it outputs for the “yes” and “no” as desired

Greg

Ok, I’m trying one more time then giving up

form.html page

<input type="checkbox" name="eat[fruit]" value="yes" />
<input type="checkbox" name="eat[bread]" value="yes" />
<input type="checkbox" name="eat[apples]" value="yes" />

Thank you! solved a lot of problems to me…
the only problem i may think about this solution is the size of the document and the size of the post data,.
i was already thinking about some very weird javascript solution.

Using arrays in form fields, as we’ve seen, can be a difficult or tedious thing to work with.

Here are a few thoughts I’ve had about this:
1. In the past when I’ve used the arrayed fields, I was less concerned with the key than I was the actual value of the field being submitted. One example that comes to mind is having multiple file uploads from one page. Sure you can map each numeric key to a field in your database, but that can be solved by creating several different named fields: file1, file2, file3, etc. I’ve used the array for situations where I don’t know how many will be submitted, which ones will be submitted, or each key, regardless of order, corresponds to a new row in a database table.

2. Rather than creating arrays that look like game[baseball], game[soccer], game[football], could you not just create single variables: baseball, soccer, football? Greg, your work-around is fine, but it accomplishes the same thing as creating $sports=array(baseball, soccer, football) and doing a foreach() on your POST array and seeing if the post key is in the $sports array.

3. I thought about what could be the best of the best solutions: fully populating the object, e.g. $sports, with all the data from the database and simply pulling the field default values when the POST field doesn’t exist (implying the unchecked checkbox). But then I got to realizing that there are going to be cases where not every database field corresponding to my $sports object is going to be represented in an HTML form, which would default the DB field every time $_POST[‘football’] wasn’t there. So I was wrong – it’s not the best of the best… for me at least.

4. How about creating an array of expected keys and default values for checkboxes in your PHP scripts? You can do that, but I think it’s too much extra work and specificity in larger apps. As much as possible I wan my apps to work with minimal additional coding. I would like to be able to extend my Games class with a BoardGame class without having to rewrite Games very much (at all), nor write a lot of code just to get BoardGame working. In my opinion $BoardGame->save(); should just work without having to write another save() method, except for those cases where differences in relational database schema need to be addressed.

Food for thought….

Cameron, I understand your point, and in programming we should try to do as little as possible. Of course that’s not laziness, it’s good practice and usually leads to unbloated code, but sometimes you just have to sit and type what’s necessary however tedious.

Using arrays for forms also allows for easier security checks.
You can foreach the POSTED array and check each key only matches a key in your created array with in_array.
As the array you create will only have key names that are allowed as per the html form, you can exit if a key name was found in the POSTED array that is not in your created array.

This checks for people posting their own form with array key values that shouldn’t be there. Posted data from users is one of the main security issues in most websites in my opinion.

Also, using a single array rather than a load of different input names also makes other sanitisation and security checking much easier for user inputted values as well as keys. As you simply run a foreach on the POSTED array and check each value for all your required checks.
I.E. is_numeric if you are only expecting a numerical value from users, EREG a-Z0-9 etc

Rather than having to duplicate the same checks for each form name, which you also have to type $_POST[‘name’] for each one as well.

I do find arrays are a lot more useful in general when working with multiple user data.
Obviously it’s not always best practice or necessary, but usually much easier.

BTW, using this you posted above-
“$sports=array(baseball, soccer, football)”
will create an array called “sports” with VALUES, not keys. The keys will be automatically assigned as numerical starting from [0]

Greg

Just wanted to let you know I appreciate you posting this solution. Even though it is overwriting a value, and that’s not necessarily standard practice, and might cause problems in other situation, it fit my scenario perfectly and has yet to cause any problems.

Kudos,
joe

Joe,

Though I haven’t come across any issues with this method yet, doesn’t mean it’s 100% perfect (though until somebody tells me otherwise, I’m going to assume it’s fine). I think the problem is that the checkbox input type should really have a default (non-checked) parameter.

This method relies on the way server-side scripts interpret form input. As far as I’ve seen it’s in a very linear fashion, which is why this works.

Greg,
Good catch ($sports array). I wrote before I thought. Your points are good, and I have no problem with doing that. In fact, it’s a rather good solution to this problem. No matter how you look at this, we should all be validating user input.

a wonderful simple way to solve this “annoying” issue, i would also suggest creative a small javascript that can update the value on change, this would be difficult and might add more code to your “simple” form for new coders, but it’s more accurate and more dynamic, anyways, as far as a form with one or two check boxes this one is a nice small trick :) good jab cam.

How do you get this to work if you do not use PHP? I need to post to a txt file all checkbox fields (checked and unchecked, different value for each) to input into excel as csv file. If no field value is posted, the field is blank in the csv eg does not exist.

@Rami, Definitely, and given a site that requires javascript (*gasp!*) for functional usage, that would be the thing to do. In that case, I would leave the name parameter off the checkbox altogether and just use the hidden field to avoid any potential problems; a quick script could also populate the boxes as well.

@Dre, This blog is here to help – most entries are things I’ve dealt with at one point or another. I’m doing my part to share the wealth :)

@vbkvbk,
You’ll need some type of server-side app to process your post data. There are services online that allow you to create forms that they process. A simple Google search should give you what you need.

Great solution, very much appreciated. The CakePHP documentation needs to have a gigantic “GOTCHA” section devoted to this stuff. Beginners like myself have wasted countless hours on nuances that weren’t otherwise obvious.

I have the exact problem. I need to do it in ASP and I’m not an ASP programmer, just try to do something quickly. How do I get rid of that comma delimited list and only get it to submit the hidden value when the box in unchecked?

Or how do I do an if statment in the submit form so that a replacement of some sort can be done?

thanks so much

This solution is back-end agnostic, so it’s up to the way your code handles POST data. I’m not familiar with ASP, but I imagine the variables you actually have access to might be whatever is written to the POST string last. That’s why the hidden input box works – the checkbox doesn’t even get sent unless it’s checked. If it was checked, the value would overwrite the value of the hidden input field. This all happens before your server gets a hold of the data. Make sense? You could also use JS to write a value to a hidden input field based on the value of the checkbox (checked/un-checked).

In JSP if you are using a bean (either via JSP tags or something else like Apache BeanUtils), you can use logic like this to make this work:

class MyBean {

Boolean checkval;

public void setCheckval (boolean b) {
if (checkval == null)
checkval = b;
else
checkval = checkval | b;
}

}

That will OR all of the “checkval” parameters together, but still leave MyBean.checkval as null if none were specified. If you aren’t using a bean, you can still apply similar logic when going through the request parameter map (go through the entire array of “checkval” values and do the same thing).

Cameron, I love your thinking with this idea.
is there any reason why we cannot do on the back end in PHP

if ( empty($_POST[‘box1’]) ) {
$my_value = 0;
} else {
$my_value = $_POST[‘box1’];
}

Or we can also evaluate for isset instead of empty().

And with this we may not even need the hidden input helper there on the form.

No?

Shony,

You can definitely do it that way, but it gets tedious if you have a lot of checkboxes – to have to pay attention to it in both your HTML and the PHP code. Consider the situation where you’re matching submitted form data against database field – only the matching set gets saved, you either have to manually write-in checks for every single checkbox field (a pain and error-prone if you forget one), or you can do something like this and not have to worry about it.

Fuckin hell! :D

Ive been going crazy about this shit for a couple of months now! AND FINALLY SOME ONE DOES THE TRICK! :D

Cant thank you enough!

wen we retrieve the value from a text box we use request.getParameter(“box1”) and request.getParameterValues(“box1”) in case of check boxes.. so wen we submit the form, which one from these shud be used?? i m bit confused.. plzz help me out..

Different IDs, as in element IDs in the HTML. The ID is unique to each element, but it’s technically OK for multiple form elements to have the same name attribute


<input type="checkbock" name="box" id="cb1" />
<input type="hidden" name="box" id="hide1" />

It’s all basic (X)HTML.

Love it.
I prefixed the field names with “bc” and then processed them in ASP with
If Left(form_field, 2) = “bc” Then
idx = Request.Form(form_field).Count
value = StringToDB(Request.Form(form_field)(idx))
Else
.
.
.
End If

I used Greg’s original thinking and it worked great for me… that is, passing the values inside defined arrays: data[1], data[2], data[3]… then in my php script a loop does the rest, if data[1] is not checked then it is null… which will lead me to:
data[1] = ”;
data[2] = ‘Y’;
data[3] = ‘Y’;

the importance is that it keeps its order that it can be called and compared whenever required…

serverside for-loop to account for unchecked checkbox values of -1

ArrayList deleteAL = new ArrayList();
for (int ii = 0; ii < deleteAL.Count; ii++)
{
if ((deleteAL[ii]).ToString() != "-1" && ii != 0)
{
deleteAL.RemoveAt(ii – 1);
}
}
So checked, checked, unchecked would return value, value, -1

Thanks for this post. Incidentally I combined this technique and some common sense for a simple solution when using arrays. Assuming you have an index you are keeping track of when generating your form (simple enough to add to any script generating the form from retrieved data). All you need to do is add the (same) index to your array for both the hidden and checkbox inputs.

I’m showing this assuming php, but it’s simple enough to extend to whatever you need:


...

...

Hope this helps and thanks again for this post!

last try… removing html brackets…

input type=”hidden” name=”field[“.$index.”]” value=”default”
input type=”checkbox” name=”field[“.$index.”]” value=”checkedval”

Instead of using any complex javascript and arrays. I tried another way, by placing js in the control itself.
We can pass both the value (default and checked) using the hidden field.
The checkbox won’t have any name tag, so it wont pass any value directly.

The code got stipped off.. Now, trying to add without html tags.

input type=’checkbox’ id=’cbMyVar’ onChange=’document.getElementById(“hdnCbMyVar”).value=(this.checked?1:0)’

input type=’hidden’ name=’cbMyVar’ id=’hdnCbMyVar’ value=’0′

Code got stripped off. Now trying without the html tags..

input type=’checkbox’ id=’cbMyVar’ onChange=’document.getElementById(“hdnCbMyVar”).value=(this.checked?1:0)’

input type=’hidden’ name=’cbMyVar’ id=’hdnCbMyVar’ value=’0′

I am unable to add the code. Trying again without the html tags..

input type=’checkbox’ id=’cbMyVar’ onChange=’document.getElementById(“hdnCbMyVar”).value=(this.checked?1:0)’

input type=’hidden’ name=’cbMyVar’ id=’hdnCbMyVar’ value=’0′

You absolute STAR! I was scratching my head as to why the database was not updating with the deselected checkbox value.

Your simple workaround works like a charm.

Thanks!

Thanks. Helped me solving problem..only problem was thet I got on server side array of two elements “0”and”1″

but Imade check box first and hiden second so I can simply checks first array element.

Thanks.

This is a fantastic tip! I just wanted to say THANK YOU THANK YOU THANK YOU for this! I was searching for a good while and then BAM your genius solution came along. Saved me hours of time. :D

I always use a simple php function to “normalize” checkbox input from a post/get…

function checkbox_value( $key ) {
return (isset($_REQUEST[$key]) && ($_REQUEST[$key]==’1′))?1:0;
}

html:

function call: $check = checkbox_value(‘checkme’);
or: $_REQUEST[‘checkme’] = checkbox_value(‘checkme’);

ugh. html. i remember that fracking checkbox nonsense from the late 1990s. it still impacts people in 2011.
it took over 10 years to figure that solution! now that is genius clever thinking. it should be bundled with the checkbox rendering code.

Thank you for great and simple solution to this mess that I spent a day fiddling with.
Only want to add that in order to display the value (e.g. you are updating a user profile with options) as checked or unchecked – all you have to do is put the inserted value (1 or 0) in an if statement like this:

<input type="checkbox" name="form_field" >

In the non-hidden row, that is.

Ok guys…. i have a simple solution for this

My only problem is, and i would REAAAAAAAALLLYY appreciate if somebody could help me out with this, how in the heck to make the checked value stay checked?? In this case the one that is not hidden…. because i am using this for a website where users can edit their profile, so lets say they checked that box and they leave the page… when they get back there it will be unchecked, so if they are changing some other field, they would have to check this box again otherwise it will post the value of the hidden check box.. UGHHH

German,

This post is more about saving a default value for a checkbox to a server. What you are asking about is how to set the checkbox to “checked.” The answer is one comment above yours. See what @Jonas had to say. If you have more specific questions, StackOverflow.com is going to be a better resource than this blog… just trying to save you some time and frustration.

Somebody owes you sexual favors for this. However, it will have to be somebody else because I don’t sting that way.

But seriously, thanks for a great solution to something that was starting to drive me crazy.

SQL> select * from week;

MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY SATURDAY SUNDAY
———- ———- ———- ———- ———- ———- ———-
0 0 0 0 0 1 1

how to select the above fields which contain the value 1 using sql query.pls help me

I have a CGI program that had this problem, but I was using array as the field name. So here’s what I did:

HTML:

CGI Handling:

idx = 0
while idx < len(POST['v']):
v = POST['v'][idx]
if v == 'hide':
v = ""
else:
# Skip the next "hide" value
idx += 1
idx += 1

I have a CGI program that had this problem, but I was using array as the field name. So here’s what I did:

HTML:

 
 

CGI Handling:

  idx = 0
  while idx < len(POST['v']):
    v = POST['v'][idx]
    if v == 'hide':
      v = ""
    else:
      # Skip the next "hide" value
      idx += 1
    idx += 1

hi Cameron,

i’m sorry, i’m still confused to implement it for many checkboxes,…

is used array or still the same name for all of checkboxes..???

i’ve tried but still couldnt get the value of unchecked from many checkboxes…

thanks before…

I’m using coldfusion with , which creates the names of the variables on the fly, so the form variable must exist when the follow up page is interpreting the data since the full name of the variable is dynamic. Using the above example, I changed it to an empty quote ( “” ) so if it’s unchecked, the name of the form variable will exist without any value and have one value if it is checked. Maybe this just works in cf.

Tested and worked in JSP. Thanks Cameron, you salved my day

P.S: I do not needed any javascript or array, just the extra hidden field worked

Ahhhhhh… A very, very important detail for JSP: To work, the hidden field must be AFTER the checkbox on the html, so that the checkbox always be the first to be read

the hidden field is good for sending true/false,on/off,1/0 to the database but then you get problems when you want to set the checkbox by data already in the database. i think checkboxes not sending and receiving data is a real bad design. data is a 2 way street, you want to save it then look at it later for corrections..this should be a NO BRAINER yet there a million posts on the internet of how to go one way or the other….i’ve seen none after weeks that address going both ways

Leave a Reply