263

I would like to show a radio button, have its value submitted, but depending on the circumstances, have it not editable. Disabled doesn't work, because it doesn't submit the value (or does it?), and it grays out the radio button. Read-only is really what I'm looking for, but for some mysterious reason it doesn't work.

Is there some weird trick I need to pull to get read-only to work as expected? Should I just do it in JavaScript instead?

Incidentally, does anyone know why read-only doesn't work in radio buttons, while it does work in other input tags? Is this one of those incomprehensible omissions in the HTML specs?

SteveC
  • 15,808
  • 23
  • 102
  • 173
mcv
  • 4,217
  • 6
  • 34
  • 40
  • 7
    “Is this one of those incomprehensible omissions in the HTML specs?” Think of it from a user’s point of view. Why display a button they can’t click? – Paul D. Waite Dec 23 '09 at 14:15
  • 90
    Why display a button they can't click? Because I want them to know the button is there, but I don't want them to be able to click it right now. But maybe later. It's a dynamic form, after all. Why would a radio button be any different from any other input field? – mcv Dec 23 '09 at 14:22
  • 8
    Here's the spec: http://www.w3.org/TR/html401/interact/forms.html#h-17.12.2 "The following elements support the readonly attribute: INPUT and TEXTAREA." Which is obviously wrong. Back here, though, we see a more accurate summary: http://www.w3.org/TR/WD-forms-970402#readonly "READONLY applies to INPUT elements of type TEXT or PASSWORD and to the TEXTAREA element." Looks like this has slipped between the gaps of recs and specs. – graphicdivine Dec 23 '09 at 14:39
  • Even more curious. According to this ancient document "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." ( http://www.htmlcodetutorial.com/forms/_INPUT_DISABLED.html ) Is this true? Does setting READONLY on a checkbox/radio lock the value, even though the user can apparently alter it? – graphicdivine Dec 23 '09 at 14:53
  • check my post [here][1] gives a clean simple solution to the issue [1]: http://stackoverflow.com/a/15513256/1861389 – driven4ward Mar 20 '13 at 01:01
  • related http://stackoverflow.com/questions/155291/can-html-checkboxes-be-set-to-readonly – Adriano Jul 17 '14 at 08:26

17 Answers17

246

Radio buttons would only need to be read-only if there are other options. If you don't have any other options, a checked radio button cannot be unchecked. If you have other options, you can prevent the user from changing the value merely by disabling the other options:

<input type="radio" name="foo" value="Y" checked>
<input type="radio" name="foo" value="N" disabled>

Fiddle: http://jsfiddle.net/qqVGu/

Sampson
  • 265,109
  • 74
  • 539
  • 565
  • 3
    The problem with your first solution is that if I want to enable the radiobutton through javascript, I suddenly have two fields with the same name, so I have to clean up one of them. Or use the hidden one for real and have the radio button just set the value of the hidden field. Ether way, it's just a bit more cumbersome than I'd like a radiobutton to be. Your second solution, although I don't doubt it works, sounds like a really ugly hack. So I guess the javascript solution is the only one that meets my criteria. I'll go with that. – mcv Dec 23 '09 at 14:28
  • Solution 2 is really a poor hack that probably won't work on less used browsers, such as "links". It also won't work on all browsers because you can TAB to it. It will just confuse the user. – Andreas Bonini Dec 23 '09 at 14:34
  • 7
    Solution 1 please! It's the only properly accessible one. And if you need to script it, it's only one more line to set the hidden field's enabledness to the opposite of the radio's enabledness. – bobince Dec 23 '09 at 14:42
  • 5
    I just noticed that solutions 2 and 3 have switched places in Jonathan's answer, so now the comments don't seem to make much sense. – mcv Dec 26 '09 at 00:32
  • 1
    Want to notice that Javascript solution is not worked, it just unchecks button. I suppose it need be `onclick="return false"` to prevent change. – dmitry Mar 08 '12 at 14:31
  • `onclick="return false"` works in FF15 and Chrome22, but an onchange event is also fired. In IE9 the existing dot is actually **unset**. Solution 1 was the only one that worked for me in all 3 browsers. If you need JS manipulation then you should give the radio buttons a prefix/suffix to prevent same element ID conflict, but its not needed for FORM submit as the last element with the same name overrides previous value however disabled elements do not submit anyway. – Kim Oct 02 '12 at 07:48
  • @Megan posted a more elegant solution below. Of course that's just my opinion. – Big McLargeHuge Sep 20 '13 at 21:43
  • 2
    When I set radio "disabled" I add "style=cursor:default" to remove "disabled cursor". – Joao Paulo May 13 '14 at 18:27
  • If a radio is readonly and there are other options, then it could not loose its checked satus if it is read only, this is sloppy programming/spec on the browser side/ hard for everyone else in the world side. So many hoops to jump trough just to make a form read only but posted. – run_the_race Sep 12 '21 at 14:23
184

I've faked readonly on a radio button by disabling only the un-checked radio buttons. It keeps the user from selecting a different value, and the checked value will always post on submit.

Using jQuery to make readonly:

$(':radio:not(:checked)').attr('disabled', true);

This approach also worked for making a select list readonly, except that you'll need to disable each un-selected option.

Megan
  • 2,534
  • 1
  • 17
  • 15
  • 9
    A variation on this to allow you to use the `readonly` property, as the OP expected it to work: `$(':radio[readonly]:not(:checked)').attr('disabled', true);` – wodow Jan 21 '14 at 14:49
  • 1
    Among the solutions below, this solution provides the cleanest code, and works well with Jquery validator since I do not need to enable/disable fields, or deal with unbinding click events and re-binding them when submitting the form. – Kristianne Nerona Apr 15 '18 at 05:34
  • Clever! Using .not(..), in case you already have a set of selected input fields: var myRadios = $('#specific-radios'); myRadios.not(':checked').prop('disabled',true); https://api.jquery.com/not/ – JoePC Jul 24 '18 at 20:08
  • Works great with elementRef in angular too – Muhammad Ahsan Jul 23 '19 at 07:58
26

This is the trick you can go with.

<input type="radio" name="name" onclick="this.checked = false;" />
Sarfraz
  • 377,238
  • 77
  • 533
  • 578
  • 4
    Exactly what I was thinking, altho it would be best if you clarified that it should be `onClick="this.checked = <%=value%>"` of some variety :) – JustLoren Dec 23 '09 at 14:16
  • that is great to know. checked can have either of true or false values. – Sarfraz Dec 23 '09 at 14:18
  • Just a warning that this won't work for those of us who browse with javascript not turned on by default. – tloach Dec 23 '09 at 14:29
  • 3
    Not a problem for my case. We use tons of jQuery and Ajax already. – mcv Dec 23 '09 at 14:45
  • 2
    Worth noting you can just do `onclick="return false;"` to keep the value the same for the group – Zach Mar 07 '18 at 00:10
  • This won't prevent the user from changing the value using the keyboard (focus the element and use arrow keys to switch value) – Alexandru Severin Aug 07 '18 at 10:14
18

I have a lengthy form (250+ fields) that posts to a db. It is an online employment application. When an admin goes to look at an application that has been filed, the form is populated with data from the db. Input texts and textareas are replaced with the text they submitted but the radios and checkboxes are useful to keep as form elements. Disabling them makes them harder to read. Setting the .checked property to false onclick won't work because they may have been checked by the user filling out the app. Anyhow...

onclick="return false;"

works like a charm for 'disabling' radios and checkboxes ipso facto.

humbolight
  • 680
  • 4
  • 13
11

The best solution is to set the checked or unchecked state (either from client or server) and to not let the user change it after wards (i.e make it readonly) do the following:

<input type="radio" name="name" onclick="javascript: return false;" />
Vipresh
  • 1,250
  • 15
  • 31
  • no! in this case, user can edit html in the browser, mark needed option as selected and post the form. – error1009 May 29 '19 at 05:54
  • 2
    They could just as easily remove the "readonly" attribute, if there was one. Or just forge the whole request with their data. Server-side validation is out of scope of this question. – ericek111 Jul 13 '21 at 09:07
2

For the non-selected radio buttons, flag them as disabled. This prevents them from responding to user input and clearing out the checked radio button. For example:

<input type="radio" name="var" checked="yes" value="Yes"></input>
<input type="radio" name="var" disabled="yes" value="No"></input>
dpolican
  • 21
  • 1
  • 5
    `checked="yes"`? What spec is that? Either use `checked="checked"` or just the attribute `checked` without a value. Same for `disabled`. – Robin van Baalen May 21 '14 at 13:28
2

JavaScript way - this worked for me.

<script>
$(document).ready(function() {
   $('#YourTableId').find('*').each(function () { $(this).attr("disabled", true); });
});
</script>

Reason:

  1. $('#YourTableId').find('*') -> this returns all the tags.

  2. $('#YourTableId').find('*').each(function () { $(this).attr("disabled", true); }); iterates over all objects captured in this and disable input tags.

Analysis (Debugging):

  1. form:radiobutton is internally considered as an "input" tag.

  2. Like in the above function(), if you try printing document.write(this.tagName);

  3. Wherever, in tags it finds radio buttons, it returns an input tag.

So, above code line can be more optimized for radio button tags, by replacing * with input: $('#YourTableId').find('input').each(function () { $(this).attr("disabled", true); });

Dr R Dizzle
  • 274
  • 2
  • 4
  • 20
2

I've come up with a javascript-heavy way to achieve a readonly state for check boxes and radio buttons. It is tested against current versions of Firefox, Opera, Safari, Google Chrome, as well as current and previous versions of IE (down to IE7).

Why not simply use the disabled property you ask? When printing the page, disabled input elements come out in a gray color. The customer for which this was implemented wanted all elements to come out the same color.

I'm not sure if I'm allowed to post the source code here, as I developed this while working for a company, but I can surely share the concepts.

With onmousedown events, you can read the selection state before the click action changes it. So you store this information and then restore these states with an onclick event.

<input id="r1" type="radio" name="group1" value="r1" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);" checked="checked">Option 1</input>
<input id="r2" type="radio" name="group1" value="r2" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);">Option 2</input>
<input id="r3" type="radio" name="group1" value="r3" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);">Option 3</input>

<input id="c1" type="checkbox" name="group2" value="c1" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);" checked="checked">Option 1</input>
<input id="c2" type="checkbox" name="group2" value="c2" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);">Option 2</input>
<input id="c3" type="checkbox" name="group2" value="c3" onmousedown="storeSelectedRadiosForThisGroup(this.name);" onclick="setSelectedStateForEachElementOfThisGroup(this.name);" checked="checked">Option 3</input>

The javascript portion of this would then work like this (again only the concepts):

var selectionStore = new Object();  // keep the currently selected items' ids in a store

function storeSelectedRadiosForThisGroup(elementName) {
    // get all the elements for this group
    var radioOrSelectGroup = document.getElementsByName(elementName);

    // iterate over the group to find the selected values and store the selected ids in the selectionStore
    // ((radioOrSelectGroup[i].checked == true) tells you that)
    // remember checkbox groups can have multiple checked items, so you you might need an array for the ids
    ...
}

function setSelectedStateForEachElementOfThisGroup(elementName) {
    // iterate over the group and set the elements checked property to true/false, depending on whether their id is in the selectionStore
    ...

    // make sure you return false here
    return false;
}

You can now enable/disable the radio buttons/checkboxes by changing the onclick and onmousedown properties of the input elements.

Tom
  • 47
  • 8
1

Try the attribute disabled, but I think the you won't get the value of the radio buttons. Or set images instead like:

<img src="itischecked.gif" alt="[x]" />radio button option

Best Regards.

Robin van Baalen
  • 3,632
  • 2
  • 21
  • 35
Tim
  • 13,228
  • 36
  • 108
  • 159
  • 1
    oh, my html code was stripped: img src="itIsChecked.gif" alt="[x]" OptionChecked – Tim Dec 23 '09 at 14:59
1

A fairly simple option would be to create a javascript function called on the form's "onsubmit" event to enable the radiobutton back so that it's value is posted with the rest of the form.
It does not seem to be an omission on HTML specs, but a design choice (a logical one, IMHO), a radiobutton can't be readonly as a button can't be, if you don't want to use it, then disable it.

wintermute
  • 433
  • 2
  • 12
1

Getting radio buttons to be read-only is pretty straightforward to accomplish. Use CSS to disable the ability of the mouse to select the radio button or it's label, and set tabindex = -1 on these elements to prevent the user from using a combination of the tab key and the spacebar to select the elements.

input[type="radio"].readonly {
    pointer-events: none;
}

label.readonly {
    pointer-events: none;
}
<input tabindex="-1" class="readonly" type="radio" name="rbgOptions" id="cbOpt1" value="Option1">
<label tabindex="-1" class="readonly" for="cbOpt1">Option 1</label>
<input tabindex="-1" class="readonly" type="radio" name="rbgOptions" id="cbOpt2" value="Option2">
<label tabindex="-1" class="readonly" for="cbIOP">Option 2</label>
zax
  • 844
  • 8
  • 14
1

I found that use onclick='this.checked = false;' worked to a certain extent. A radio button that was clicked would not be selected. However, if there was a radio button that was already selected (e.g., a default value), that radio button would become unselected.

<!-- didn't completely work -->
<input type="radio" name="r1" id="r1" value="N" checked="checked" onclick='this.checked = false;'>N</input>
<input type="radio" name="r1" id="r1" value="Y" onclick='this.checked = false;'>Y</input>

For this scenario, leaving the default value alone and disabling the other radio button(s) preserves the already selected radio button and prevents it from being unselected.

<!-- preserves pre-selected value -->
<input type="radio" name="r1" id="r1" value="N" checked="checked">N</input>
<input type="radio" name="r1" id="r1" value="Y" disabled>Y</input>

This solution is not the most elegant way of preventing the default value from being changed, but it will work whether or not javascript is enabled.

JW8
  • 1,496
  • 5
  • 21
  • 36
0

I'm using a JS plugin that styles checkbox/radio input elements and used the following jQuery to establish a 'readonly state' where the underlying value is still posted but the input element appears inaccessible to the user, which is I believe the intended reason we would use a readonly input attribute...

if ($(node).prop('readonly')) {
    $(node).parent('div').addClass('disabled'); // just styling, appears greyed out
    $(node).on('click', function (e) {
        e.preventDefault();
    });
}
chopstik
  • 363
  • 2
  • 10
0

Here is my solution (override) for Sencha ExtJS 7.2+ (checkbox and radio in a single override)


Ext.define('MyApp.override.field.Checkbox', {
    override: 'Ext.field.Checkbox',

    /**
     * OVERRIDE: to allow updateReadOnly to work propperly
     * @param {boolean} newValue
     *
     * To ensure the disabled state stays active if the field is still readOnly
     * we re - set the disabled state
     */
    updateDisabled(newValue) {
        this.callParent(arguments);

        if (!newValue && this.getReadOnly()) {
            this.inputElement.dom.disabled = true;
        }
    },

    /**
     * OVERRIDE: readonly for radiogroups and checkboxgroup do not work as other fields
     *     https://stackoverflow.com/questions/1953017/why-cant-radio-buttons-be-readonly
     *
     * @param {boolean} newValue
     *
     *  - use disabled on the field
     */
    updateReadOnly(value) {
        this.callParent(arguments);

        if (!this.getDisabled()) {
            this.inputElement.dom.disabled = value;
        }
    }
});
Dinkheller
  • 4,631
  • 5
  • 39
  • 67
0

Disabled works on individual radio buttons (not the whole set). If you are using PHP and your circumstances are known on the server before loading the page in the browser you can use this very simple solution.

<php $chcky= (condition) ? 'checked' : 'disabled';?>
<php $chckn= (condition) ? 'checked' : 'disabled';?>
<input type="radio" name="var" value="Yes" <?php echo $chcky?>></input>
<input type="radio" name="var" value="No" <?php echo $chckn?>></input>

I use it on the page responding a form submission.

0

Extract from https://stackoverflow.com/a/71086058/18183749

If you can't use the 'disabled' attribut (as it erases the value's input at POST), and noticed that html attribut 'readonly' works only on textarea and some input(text, password, search, as far I've seen), and finally, if you don't want to bother with duplicating all your select, checkbox and radio with hidden input, you might find the following function or any of his inner logics to your liking :

addReadOnlyToFormElements = function (idElement) {
    // html readonly don't work on input of type checkbox and radio, neither on select. So, a safe trick is to disable the non-selected items
    $('#' + idElement + ' input[type="radio"]:not(:checked)').prop('disabled',true); 

    // and, on the selected ones, mimic readonly appearance
    $('#' + idElement + ' input[type="radio"]:checked').css('opacity','0.5');
}

And there's nothing easier than to remove these readonly

removeReadOnlyFromFormElements = function (idElement) {
    // Remove the disabled attribut on non-selected
    $('#' + idElement + ' input[type="radio"]:not(:checked)').prop('disabled',false); 
 
    // Remove readonly appearance on selected ones
    $('#' + idElement + ' input[type="radio"]:checked').css('opacity','');
}
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
-2

What about capturing an "On_click()" event in JS and checking it like here?:

http://www.dynamicdrive.com/forums/showthread.php?t=33043

Ben Usman
  • 7,969
  • 6
  • 46
  • 66