885
votes

I thought they could be, but as I'm not putting my money where my mouth was (so to speak) setting the readonly attribute doesn't actually seem to do anything.

I'd rather not use Disabled, since I want the checked check boxes to be submitted with the rest of the form, I just don't want the client to be able to change them under certain circumstances.

30
A (malicious) client can always change a checkbox's value (or send arbitrary requests). Always make sure you do proper server-side validation!knittl
@knittl But a normal vistor has no (malicious) client. And a normal Vistor did not want to change a information (That is the sence of readonly)Christian Gollhardt
@knittl You seem to dismiss the entire sense of readonly! Why then this attribute would exist!Izhar Aazmi
@IzharAazmi: readonly is only a client-side attribute to help a browser properly render a site and then construct the correct request from it. The server cannot and should not know about the readonly attribute of the rendered page. It must assume the request came from anywhere (and possibly with malicious intentions); never rely on user-provided input. Still, why send a checkbox's value which you cannot edit in a request (if you set the value before rendering, you already know the value when the request is submitted, so there's no need to transmit it in the request)knittl
@knittl I agree! But you see readonly attribute exists there for some reason. It has certainly nothing to do with server side implementation. But it is there to tell the user "Hey! This value is being assumed here, and/but you cannot change this."Izhar Aazmi

30 Answers

607
votes

you can use this:

<input type="checkbox" onclick="return false;"/>

This works because returning false from the click event stops the chain of execution continuing.

438
votes

READONLY doesn't work on checkboxes as it prevents you from editing a field's value, but with a checkbox you're actually editing the field's state (on || off)

From faqs.org:

It's important to understand that READONLY merely prevents the user from changing the value of the field, not from interacting with the field. In checkboxes, for example, you can check them on or off (thus setting the CHECKED state) but you don't change the value of the field.

If you don't want to use disabled but still want to submit the value, how about submitting the value as a hidden field and just printing its contents to the user when they don't meet the edit criteria? e.g.

// user allowed change
if($user_allowed_edit)
{
    echo '<input type="checkbox" name="my_check"> Check value';
}
else
{
    // Not allowed change - submit value..
    echo '<input type="hidden" name="my_check" value="1" />';
    // .. and show user the value being submitted
    echo '<input type="checkbox" disabled readonly> Check value';
}
366
votes

This is a checkbox you can't change:

<input type="checkbox" disabled="disabled" checked="checked">

Just add disabled="disabled" as an attribute.


Edit to address the comments:

If you want the data to be posted back, than a simple solutions is to apply the same name to a hidden input:

<input name="myvalue" type="checkbox" disabled="disabled" checked="checked"/>
<input name="myvalue" type="hidden" value="true"/>

This way, when the checkbox is set to 'disabled', it only serves the purpose of a visual representation of the data, instead of actually being 'linked' to the data. In the post back, the value of the hidden input is being sent when the checkbox is disabled.

67
votes
<input type="checkbox" onclick="this.checked=!this.checked;">

But you absolutely MUST validate the data on the server to ensure it hasn't been changed.

57
votes

another "simple solution":

<!-- field that holds the data -->
<input type="hidden" name="my_name" value="1" /> 
<!-- visual dummy for the user -->
<input type="checkbox" name="my_name_visual_dummy" value="1" checked="checked" disabled="disabled" />

disabled="disabled" / disabled=true

45
votes

This presents a bit of a usability issue.

If you want to display a checkbox, but not let it be interacted with, why even a checkbox then?

However, my approach would be to use disabled (The user expects a disabled checkbox to not be editable, instead of using JS to make an enabled one not work), and add a form submit handler using javascript that enables checkboxes right before the form is submitted. This way you you do get your values posted.

ie something like this:

var form = document.getElementById('yourform');
form.onSubmit = function () 
{ 
    var formElems = document.getElementsByTagName('INPUT');
    for (var i = 0; i , formElems.length; i++)
    {  
       if (formElems[i].type == 'checkbox')
       { 
          formElems[i].disabled = false;
       }
    }
}
39
votes
<input type="checkbox" readonly="readonly" name="..." />

with jquery:

$(':checkbox[readonly]').click(function(){
            return false;
        });

it still might be a good idea to give some visual hint (css, text,...), that the control won't accept inputs.

22
votes

I used this to achieve the results:

<input type=checkbox onclick="return false;" onkeydown="return false;" />
19
votes

Belated answer, but most answers seem to over complicate it.

As I understand it, the OP was basically wanting:

  1. Readonly checkbox to show status.
  2. Value returned with form.

It should be noted that:

  1. The OP preferred not to use the disabled attribute, because they 'want the checked check boxes to be submitted with the rest of the form'.
  2. Unchecked checkboxes are not submitted with the form, as the quote from the OP in 1. above indicates they knew already. Basically, the value of the checkbox only exists if it is checked.
  3. A disabled checkbox clearly indicates that it cannot be changed, by design, so a user is unlikely to attempt to change it.
  4. The value of a checkbox is not limited to indicating its status, such as yes or false, but can be any text.

Therefore, since the readonly attribute does not work, the best solution, requiring no javascript, is:

  1. A disabled checkbox, with no name or value.
  2. If the checkbox is to be displayed as checked, a hidden field with the name and value as stored on the server.

So for a checked checkbox:

<input type="checkbox" checked="checked" disabled="disabled" />
<input type="hidden" name="fieldname" value="fieldvalue" />

For an unchecked checkbox:

<input type="checkbox" disabled="disabled" />

The main problem with disabled inputs, especially checkboxes, is their poor contrast which may be a problem for some with certain visual disabilities. It may be better to indicate a value by plain words, such as Status: none or Status: implemented, but including the hidden input above when the latter is used, such as:

<p>Status: Implemented<input type="hidden" name="status" value="implemented" /></p>
13
votes

I happened to notice the solution given below. In found it my research for the same issue. I don't who had posted it but it wasn't made by me. It uses jQuery:

$(document).ready(function() {
    $(":checkbox").bind("click", false);
});

This would make the checkboxes read only which would be helpful for showing readonly data to the client.

13
votes

Most of the current answers have one or more of these problems:

  1. Only check for mouse not keyboard.
  2. Check only on page load.
  3. Hook the ever-popular change or submit events which won't always work out if something else has them hooked.
  4. Require a hidden input or other special elements/attributes that you have to undo in order to re-enable the checkbox using javascript.

The following is simple and has none of those problems.

$('input[type="checkbox"]').on('click keyup keypress keydown', function (event) {
    if($(this).is('[readonly]')) { return false; }
});

If the checkbox is readonly, it won't change. If it's not, it will. It does use jquery, but you're probably using that already...

It works.

9
votes
onclick="javascript: return false;"
9
votes

If you want them to be submitted to the server with form but be not interacive for user, you can use pointer-events: none in css (works in all modern browsers except IE10- and Opera 12-) and set tab-index to -1 to prevent changing via keyboard. Also note that you can't use label tag as click on it will change the state anyway.

input[type="checkbox"][readonly] {
  pointer-events: none !important;
}

td {
  min-width: 5em;
  text-align: center;
}

td:last-child {
  text-align: left;
}
<table>
  <tr>
    <th>usual
    <th>readonly
    <th>disabled
  </tr><tr>
    <td><input type=checkbox />
    <td><input type=checkbox readonly tabindex=-1 />
    <td><input type=checkbox disabled />
    <td>works
  </tr><tr>
    <td><input type=checkbox checked />
    <td><input type=checkbox readonly checked tabindex=-1 />
    <td><input type=checkbox disabled checked />
    <td>also works
  </tr><tr>
    <td><label><input type=checkbox checked /></label>
    <td><label><input type=checkbox readonly checked tabindex=-1 /></label>
    <td><label><input type=checkbox disabled checked /></label>
    <td>broken - don't use label tag
  </tr>
</table>
7
votes
<input name="isActive" id="isActive" type="checkbox" value="1" checked="checked" onclick="return false"/>
7
votes

I would use the readonly attribute

<input type="checkbox" readonly>

Then use CSS to disable interactions:

input[type='checkbox'][readonly]{
    pointer-events: none;
}

Note that using the pseudo-class :read-only doesn't work here.

input[type='checkbox']:read-only{ /*not working*/
    pointer-events: none;
}
6
votes

<input type="checkbox" onclick="return false" /> will work for you , I am using this

4
votes

Some of the answers on here seem a bit roundabout, but here's a small hack.

<form id="aform" name="aform" method="POST">
    <input name="chkBox_1" type="checkbox" checked value="1" disabled="disabled" />
    <input id="submitBttn" type="button" value="Submit" onClick='return submitPage();'>
</form>​

then in jquery you can either choose one of two options:

$(document).ready(function(){
    //first option, you don't need the disabled attribute, this will prevent
    //the user from changing the checkbox values
    $("input[name^='chkBox_1']").click(function(e){
        e.preventDefault();
    });

    //second option, keep the disabled attribute, and disable it upon submit
    $("#submitBttn").click(function(){
        $("input[name^='chkBox_1']").attr("disabled",false);
        $("#aform").submit();
    });

});

demo: http://jsfiddle.net/5WFYt/

4
votes

Building on the above answers, if using jQuery, this may be an good solution for all inputs:

<script>
    $(function () {
        $('.readonly input').attr('readonly', 'readonly');
        $('.readonly textarea').attr('readonly', 'readonly');
        $('.readonly input:checkbox').click(function(){return false;});
        $('.readonly input:checkbox').keydown(function () { return false; });
    });
</script>

I'm using this with Asp.Net MVC to set some form elements read only. The above works for text and check boxes by setting any parent container as .readonly such as the following scenarios:

<div class="editor-field readonly">
    <input id="Date" name="Date" type="datetime" value="11/29/2012 4:01:06 PM" />
</div>
<fieldset class="flags-editor readonly">
     <input checked="checked" class="flags-editor" id="Flag1" name="Flags" type="checkbox" value="Flag1" />
</fieldset>
4
votes
<input type="radio" name="alwaysOn" onchange="this.checked=true" checked="checked">
<input type="radio" name="alwaysOff" onchange="this.checked=false" >
4
votes

I know that "disabled" isn't an acceptable answer, since the op wants it to post. However, you're always going to have to validate values on the server side EVEN if you have the readonly option set. This is because you can't stop a malicious user from posting values using the readonly attribute.

I suggest storing the original value (server side), and setting it to disabled. Then, when they submit the form, ignore any values posted and take the original values that you stored.

It'll look and behave like it's a readonly value. And it handles (ignores) posts from malicious users. You're killing 2 birds with one stone.

4
votes

No, input checkboxes can't be readonly.

But you can make them readonly with javascript!

Add this code anywhere at any time to make checkboxes readonly work as assumed, by preventing the user from modifying it in any way.

jQuery(document).on('click', function(e){
      // check for type, avoid selecting the element for performance
      if(e.target.type == 'checkbox') {
          var el = jQuery(e.target);
          if(el.prop('readonly')) {
              // prevent it from changing state
              e.preventDefault();
          }
      }
});
input[type=checkbox][readonly] {
    cursor: not-allowed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label><input type="checkbox" checked readonly> I'm readonly!</label>

You can add this script at any time after jQuery has loaded.

It will work for dynamically added elements.

It works by picking up the click event (that happens before the change event) on any element on the page, it then checks if this element is a readonly checkbox, and if it is, then it blocks the change.

There are so many ifs to make it not affect the performance of the page.

3
votes

I would have commented on ConroyP's answer, but that requires 50 reputation which I don't have. I do have enough reputation to post another answer. Sorry.

The problem with ConroyP's answer is that the checkbox is rendered unchangeable by not even including it on the page. Although Electrons_Ahoy does not stipulate as much, the best answer would be one in which the unchangeable checkbox would look similar, if not the same as, the changeable checkbox, as is the case when the "disabled" attribute is applied. A solution which addresses the two reasons Electrons_Ahoy gives for not wanting to use the "disabled" attribute would not necessarily be invalid because it utilized the "disabled" attribute.

Assume two boolean variables, $checked and $disabled :

if ($checked && $disabled)
    echo '<input type="hidden" name="my_name" value="1" />';
echo '<input type="checkbox" name="my_name" value="1" ',
    $checked ? 'checked="checked" ' : '',
    $disabled ? 'disabled="disabled" ' : '', '/>';

The checkbox is displayed as checked if $checked is true. The checkbox is displayed as unchecked if $checked is false. The user can change the state of the checkbox if and only if $disabled is false. The "my_name" parameter is not posted when the checkbox is unchecked, by the user or not. The "my_name=1" parameter is posted when the checkbox is checked, by the user or not. I believe this is what Electrons_Ahoy was looking for.

3
votes

readonly does not work with <input type='checkbox'>

So, if you need to submit values from disabled checkboxes in a form, you can use jQuery:

$('form').submit(function(e) {
    $('input[type="checkbox"]:disabled').each(function(e) {
        $(this).removeAttr('disabled');
    })
});

This way the disabled attributes are removed from the elements when submitting the form.

2
votes

Just use simple disabled tag like this below.

<input type="checkbox" name="email"  disabled>
2
votes

If you want ALL your checkboxes to be "locked" so user can't change the "checked" state if "readonly" attibute is present, then you can use jQuery:

$(':checkbox').click(function () {
    if (typeof ($(this).attr('readonly')) != "undefined") {
        return false;
    }
});

Cool thing about this code is that it allows you to change the "readonly" attribute all over your code without having to rebind every checkbox.

It works for radio buttons as well.

1
votes

Very late to the party but I found an answer for MVC (5) I disabled the CheckBox and added a HiddenFor BEFORE the checkbox, so when it is posting if finds the Hidden field first and uses that value. This does work.

 <div class="form-group">
     @Html.LabelFor(model => model.Carrier.Exists, new { @class = "control-label col-md-2" })
         <div class="col-md-10">
              @Html.HiddenFor(model => model.Carrier.Exists)
              @Html.CheckBoxFor(model => model.Carrier.Exists, new { @disabled = "disabled" })
              @Html.ValidationMessageFor(model => model.Carrier.Exists)
          </div>
 </div>
0
votes

I just don't want the client to be able to change them under certain circumstances.

READONLY itself won't work. You may be able to do something funky w/CSS but we usually just make them disabled.

WARNING: If they're posted back then the client can change them, period. You can't rely on readonly to prevent a user from changing something. The could always use fiddler or just chane the html w/firebug or some such thing.

0
votes

The main reason people would like a read-only check-box and (as well) a read-only radio-group is so that information that cannot be changed can be presented back to the user in the form it was entered.

OK disabled will do this -- unfortunately disabled controls are not keyboard navigable and therefore fall foul of all accessibility legislation. This is the BIGGEST hangup in HTML that I know of.

0
votes

Contributing very very late...but anyway. On page load, use jquery to disable all checkboxes except the currently selected one. Then set the currently selected one as read only so it has a similar look as the disabled ones. User cannot change the value, and the selected value still submits.

0
votes

If you need the checkbox to be submitted with the form but effectively read-only to the user, I recommend setting them to disabled and using javascript to re-enable them when the form is submitted.

This is for two reasons. First and most important, your users benefit from seeing a visible difference between checkboxes they can change and checkboxes which are read-only. Disabled does this.

Second reason is that the disabled state is built into the browser so you need less code to execute when the user clicks on something. This is probably more of a personal preference than anything else. You'll still need some javascript to un-disable these when submitting the form.

It seems easier to me to use some javascript when the form is submitted to un-disable the checkboxes than to use a hidden input to carry the value.