Unlike check boxes, it is impossible for the user to deselect radio buttons once they are clicked. Is there any way so that they can be toggled programmatically using Javascript? This would be preferably without using jQuery.
This question is related to
javascript
html
radio-button
Radio buttons are meant to be used in groups, as defined by their sharing the same name
attribute. Then clicking on one of them deselects the currently selected one. To allow the user to cancel a “real” selection he has made, you can include a radio button that corresponds to a null choice, like “Do not know” or “No answer”.
If you want a single button that can be checked or unchecked, use a checkbox.
It is possible (but normally not relevant) to uncheck a radio button in JavaScript, simply by setting its checked
property to false, e.g.
<input type=radio name=foo id=foo value=var>
<input type=button value="Uncheck" onclick=
"document.getElementById('foo').checked = false">
while it was asked in terms of javascript, the adaption from jquery is trivial... with this method you can check for the "null" value and pass it...
var checked_val = "null";_x000D_
$(".no_option").on("click", function(){_x000D_
if($(this).val() == checked_val){_x000D_
$('input[name=group][value=null]').prop("checked",true);_x000D_
checked_val = "null";_x000D_
}else{_x000D_
checked_val = $(this).val();_x000D_
}_x000D_
});
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>_x000D_
<input type="radio" name="group" class="no_option" value="0">option 0<br>_x000D_
<input type="radio" name="group" class="no_option" value="1">option 1<br>_x000D_
<input type="radio" name="group" class="no_option" value="2">option 2<br>_x000D_
<input type="radio" name="group" class="no_option" value="3">option 3<br>_x000D_
<input type="radio" name="group" class="no_option" value="4">option 4<br>_x000D_
<input type="radio" name="group" class="no_option" value="5">option 5<br>_x000D_
<input type="radio" name="group" class="no_option" value="6">option 6<br>_x000D_
<input type="radio" name="group" class="no_option" value="null" style="display:none">
_x000D_
Old question but people keep coming from Google here and OP asked preferably without jQuery, so here is my shot.
Should works even on IE 9
// iterate using Array method for compatibility_x000D_
Array.prototype.forEach.call(document.querySelectorAll('[type=radio]'), function(radio) {_x000D_
radio.addEventListener('click', function(){_x000D_
var self = this;_x000D_
// get all elements with same name but itself and mark them unchecked_x000D_
Array.prototype.filter.call(document.getElementsByName(this.name), function(filterEl) {_x000D_
return self !== filterEl;_x000D_
}).forEach(function(otherEl) {_x000D_
delete otherEl.dataset.check_x000D_
})_x000D_
_x000D_
// set state based on previous one_x000D_
if (this.dataset.hasOwnProperty('check')) {_x000D_
this.checked = false_x000D_
delete this.dataset.check_x000D_
} else {_x000D_
this.dataset.check = ''_x000D_
}_x000D_
}, false)_x000D_
})
_x000D_
<label><input type="radio" name="foo" value="1"/>foo = 1</label><br/>_x000D_
<label><input type="radio" name="foo" value="2"/>foo = 2</label><br/>_x000D_
<label><input type="radio" name="foo" value="3"/>foo = 3</label><br/>_x000D_
<br/>_x000D_
<label><input type="radio" name="bar" value="1"/>bar = 1</label><br/>_x000D_
<label><input type="radio" name="bar" value="2"/>bar = 2</label><br/>_x000D_
<label><input type="radio" name="bar" value="3"/>bar = 3</label><br/>
_x000D_
Unfortunately it does not work in Chrome or Edge, but it does work in FireFox:
$(document)
// uncheck it when clicked
.on("click","input[type='radio']", function(){ $(this).prop("checked",false); })
// re-check it if value is changed to this input
.on("change","input[type='radio']", function(){ $(this).prop("checked",true); });
I will try to make a small answer with 3 radio buttons, you can add stuff later on.
const radios = Array.from(document.getElementsByClassName('radio'))
for(let i of radios) {
i.state = false
i.onclick = () => {
i.checked = i.state = !i.state
for(let j of radios)
if(j !== i) j.checked = j.state = false
}
}
_x000D_
<input class="radio" type="radio">X
<input class="radio" type="radio">Y
<input class="radio" type="radio">Z
_x000D_
Now I wanted to implement this on my rails project, which has multiple forms (depends, fetched from database), each form has 2 visible radio buttons + 1 hidden radio button.
I want the user the select / deselect the radio button of each form. And selecting one on a form shouldn't deselect the other selected button on another form. So I rather did this:
var radios = Array.from(document.getElementsByClassName('radio'))
for (let i of radios) {
i.state = false
i.onclick = () => {
i.checked = i.state = !i.state
for (let j of radios)
if (j !== i) j.state = false
}
}
_x000D_
<form>
<input class="radio" name="A" type="radio">A
<input class="radio" name="A" type="radio">B
<input class="radio" name="A" type="radio">C
</form>
<form>
<input class="radio" name="A" type="radio">D
<input class="radio" name="A" type="radio">E
<input class="radio" name="A" type="radio">F
</form>
<form>
<input class="radio" name="SOMETHING" type="radio">G
<input class="radio" name="SOMETHING" type="radio">H
<input class="radio" name="SOMETHING" type="radio">I
</form>
_x000D_
You see all have the same name, but they are in a different forms, grouped by 3, so this works for multiple forms.
Here's an example of where it is arguably appropriate to uncheck radio buttons other than by making a new selection. I have a dictionary whose entries can be selected using a variety of indices. Which index to use is selected by means of a set of radio buttons. However, there is also a "random entry" button that the user can use if he or she just wants to browse. Leaving an index in place when the entry has been selected by means of the random entry button would be misleading, so when this button is pressed, I uncheck all of the index selection radio buttons and replace the contents of the index frame with an empty page.
A working bug free update to Shmili Breuer answer.
(function() {
$( "input[type='radio'].revertible" ).click(function() {
var $this = $( this );
// update and remove the previous checked class
var $prevChecked = $('input[name=' + $this.attr('name') + ']:not(:checked).checked');
$prevChecked.removeClass('checked');
if( $this.hasClass("checked") ) {
$this.removeClass("checked");
$this.prop("checked", false);
}
else {
$this.addClass("checked");
}
});
})();
If you are looking for solution in jQuery here it is. It is similar to this
$('input:radio').click(function() {
let name = $(this).attr('name');
let self = $(this);
[].filter.call($(`input[name=${name}]`), function(ele){
return self[0] !== $(ele)[0];
}).forEach(function(otherEle){
$(otherEle).removeAttr('data-check');
});
if($(this).attr('data-check')){
$(this).prop("checked", false);
$(this).removeAttr('data-check');
}else{
$(this).attr("data-check", "1");
}
});
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<input class="radio" name="A" type="radio">A
<input class="radio" name="A" type="radio">B
<input class="radio" name="A" type="radio">C
</form>
<form>
<input class="radio" name="B" type="radio">D
<input class="radio" name="B" type="radio">E
<input class="radio" name="B" type="radio">F
</form>
<form>
<input class="radio" name="C" type="radio">G
<input class="radio" name="C" type="radio">H
<input class="radio" name="C" type="radio">I
</form>
_x000D_
This is my answer (though I made it with jQuery but only for the purpose of selecting elements and to add and remove a class, so you can easily replace it with pure JS selectors & pure JS add attribute )
<input type='radio' name='radioBtn'>
<input type='radio' name='radioBtn'>
<input type='radio' name='radioBtn'>
$(document).on("click", "input[name='radioBtn']", function(){
thisRadio = $(this);
if (thisRadio.hasClass("imChecked")) {
thisRadio.removeClass("imChecked");
thisRadio.prop('checked', false);
} else {
thisRadio.prop('checked', true);
thisRadio.addClass("imChecked");
};
})
The code below will do the trick.
$('input[type=radio]').click(function() {_x000D_
if($(this).hasClass("checked")){_x000D_
this.checked = false;_x000D_
$(this).removeClass("checked")_x000D_
}else{_x000D_
$(this).addClass("checked")_x000D_
}_x000D_
});
_x000D_
I came here because I had the same issue. I wanted to present the options to the user while leaving the option of remaining empty. Although this is possible to explicitly code using checkboxes that would complicate the back end.
Having the user Control+click is almost as good as having them uncheck it through the console. Catching the mousedown is to early and onclick is too late.
Well, at last here is a solution! Just put these few lines once on the page and you have it made for all radio buttons on the page. You can even fiddle with the selector to customize it.
window.onload = function() {_x000D_
document.querySelectorAll("INPUT[type='radio']").forEach(function(rd) {_x000D_
rd.addEventListener("mousedown", function() {_x000D_
if(this.checked) {_x000D_
this.onclick=function() {_x000D_
this.checked=false_x000D_
}_x000D_
} else {_x000D_
this.onclick=null_x000D_
}_x000D_
})_x000D_
})_x000D_
}
_x000D_
<input type=radio name=unchecksample> Number One<br>_x000D_
<input type=radio name=unchecksample> Number Two<br>_x000D_
<input type=radio name=unchecksample> Number Three<br>_x000D_
<input type=radio name=unchecksample> Number Four<br>_x000D_
<input type=radio name=unchecksample> Number Five<br>
_x000D_
Extending user3716078's answer to allow multiple independent radio button groups and a neater way of assigning event listeners to multiple elements...
window.onload = function() {
var acc_checked=[];
[].slice.call(document.querySelectorAll('.accordion input[type="radio"]')).forEach(function(el,i){
/**
* i represents the integer value of where we are in the loop
* el represents the element in question in the current loop
*/
el.addEventListener('click', function(e){
if(acc_checked[this.name] != this) {
acc_checked[this.name] = this;
} else {
this.checked = false;
acc_checked[this.name] = null;
}
}, false);
});
}
You cannot easily implement uncheck trivially via if(this.checked) this.checked = false
, (if you really want to, see the hacker way at the end) because the events fire in this order:
mousedown
or keydown
mouseup
or keyup
click
input
(only if state is changed)change
(only if state is changed)Now in which event to perform the mentioned uncheck?
mouseup
or mousedown
: then the step 3 the value is set back to true and change and input event doesn't even fire as the state didn't change when they are called in the sequence - so you can't uncheck it hereclick
: then the state is always false and input and change also doesn't fire - so you can't check itinput
or change
: it doesn't fire when the state is not changed and clicking selected element doesn't change the state - so you can't do anything useful hereAs you can learn from the sequence above, the way is:
mouseup
click
as negation of previous stateIf you want to store the previous state in data attribute, keep in mind that it is saved as string, whereas the checked attribute is boolean. So you can implement it like:
radio.onmouseup = function() { this.dataset.checked = this.checked? 1 : ""; }
radio.onclick = function() { this.checked = !this.dataset.checked; }
It seemingly works, but you should not do this for these reasons:
mousedown
somewhere else, then hover above radio button, then mouseup
: in this case mouseup fires and click does notThere is another issue: dynamically added radio buttons. There are two ways:
element.appendChild(radio)
- if you enable deselect on all radios in DOMContentLoaded
event, this dynamically added radio is not affectedelement.innerHTML+= '<input type="radio">'
- effectively replaces the HTML contents of the element and re-creates DOM inside it - so all event listeners are discardedTo solve (2), I recommend onclick content attribute. Note that element.onclick = fn
and element.setAttribute("onclick", "fn()")
are two different things. Also note that onclick
fires everytime the user activates the radio, regardless of the interface he used.
Yet another issue: if you enable deselect, then you should also enable switching by Space to mimic checkboxes behaviour. The following code solves all mentioned issues:
function deselectableRadios(rootElement) {
if(!rootElement) rootElement = document;
if(!window.radioChecked) window.radioChecked = null;
window.radioClick = function(e) {
const obj = e.target;
if(e.keyCode) return obj.checked = e.keyCode!=32;
obj.checked = window.radioChecked != obj;
window.radioChecked = obj.checked ? obj : null;
}
rootElement.querySelectorAll("input[type='radio']").forEach( radio => {
radio.setAttribute("onclick", "radioClick(event)");
radio.setAttribute("onkeyup", "radioClick(event)");
});
}
deselectableRadios();
_x000D_
<label><input type="radio" name="tag1">one</label>
<label><input type="radio" name="tag1">two</label>
<label><input type="radio" name="tag1">three</label>
<label><input type="radio" name="tag1">four</label>
_x000D_
Now you can call deselectableRadios()
anytime you dynamically add content and calling it on radios multiple times doesn't break it. You can also specify the rootElement
to update only a subtree of HTML DOM and make your web faster. If you don't like the global state, you can use the hacker way:
The point is to abuse setTimeout
on mouseup
to call it after the checked property is set:
function deselectable() {
setTimeout(checked => this.checked = !checked, 0, this.checked);
}
Now you can make any radio button deselectable:
radio.onmouseup = deselectable;
But this simple one-liner works just with clicking and doesn't solve the issues mentioned above.
Deselectable radio is basically checkbox where only one in the group can be checked. If your browser supports the appearance CSS4 feature, you can simply
<input type="checkbox" name="foo" style="appearance: radio">
and then in onclick
event getElementsByName("foo")
and uncheck all remaining checkboxes of the name (checkboxes doesn't send value if they are not checked).
This almost worked for me.
<input type='radio' name='radioBtn'>
<input type='radio' name='radioBtn'>
<input type='radio' name='radioBtn'>
$(document).on("click", "input[name='radioBtn']", function(){
thisRadio = $(this);
if (thisRadio.hasClass("imChecked")) {
thisRadio.removeClass("imChecked");
thisRadio.prop('checked', false);
} else {
thisRadio.prop('checked', true);
thisRadio.addClass("imChecked");
};
})
But If I check a radio button, then check another and try to check the first one again I must do two clicks. This is because it has the class imChecked. I just needed to uncheck the other radio buttons before the verification.
Add this line makes it work:
$("input[name='radioBtn']").not(thisRadio).removeClass("imChecked");
<input type='radio' name='radioBtn'>
<input type='radio' name='radioBtn'>
<input type='radio' name='radioBtn'>
$(document).on("click", "input[name='radioBtn']", function(){
thisRadio = $(this);
$("input[name='radioBtn']").not(thisRadio).removeClass("imChecked");
if (thisRadio.hasClass("imChecked")) {
thisRadio.removeClass("imChecked");
thisRadio.prop('checked', false);
} else {
thisRadio.prop('checked', true);
thisRadio.addClass("imChecked");
};
})
The full code will look something like this
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>
<body>
<input name="radio" type="radio" id="myRadio" value="myRadio" checked="checked" onclick="setRadio(this)" />
<label for="myRadio"></label>
<script language="javascript">
function setRadio(obj)
{
obj.checked = false;
}
</script>
</body>
</html>
Let's suppose you have a button where on clicking it, you can make all your radio button selection to false. You can write the below code inside the onclick handler.
Below code take radio buttons based on class name and for each element it will mark it to false.
var elements=document.getElementsByClassName('Button');
Array.prototype.forEach.call(elements, function(element) {
element.checked = false;
});
Full example in pure JavaScript :
box.onmouseup = function() {_x000D_
var temp = this.children[0];_x000D_
if (temp.checked) {_x000D_
setTimeout(function() {_x000D_
temp.checked = false;_x000D_
}, 0);_x000D_
}_x000D_
}
_x000D_
<label id='box' style='margin-right: 1em;'>_x000D_
<input type='radio' name='chk_préf_méd_perso' value='valeur'>_x000D_
libellé_x000D_
</label>
_x000D_
I'm surprised no-one has posted this "neat trick" version which doesn't use any JavaScript, it only uses CSS.
#radio1 {
display: none;
}
#wrapper {
/* NOTE: This wrapper div is not needed provided you can position the label for #radio1 on top of #radio2 using some other technique. */
position: relative;
}
#radio1:not(:checked) ~ * label[for="radio1"] {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
#radio1:checked ~ * label[for="radio1"] {
display: none;
}
/* Non-essential styles: */
label[for],
label:not([for="radio1"]) {
cursor: pointer;
border-radius: 7px;
}
label[for]:hover + label,
label:not([for="radio1"]):hover {
background-color: #ccc;
}
_x000D_
<input type="radio" name="group1" id="radio1" checked="checked" />
<p>Look mum, <strong>no JavaScript!</strong></p>
<div id="wrapper">
<label for="radio1"></label>
<label>
<input type="radio" name="group1" id="radio2" />
You can toggle me on and off!
</label>
</div>
_x000D_
#radio1
(<input type="radio" id="radio2" />
) is always hidden.:checked
and :not(:checked)
pseudo-class selectors with sibling selectors (+
and ~
) allow other elements' style to be affected depending on whether or not an <input type="checkbox" />
or <input type="radio" />
is checked.
#radio1
is un-checked (or when #radio2
is checked) that causes a <label>
to be overlayed on-top of #radio2
and that label has for="radio1"
, so clicking it will cause #radio1
to be checked, not #radio2
.:has()
selector function is supported but as of November 2020 only PrinceXML supports :has()
and it's currently looking like :has()
will be dropped from CSS4 entirely owing to the difficulty of implementation.This approach can be scaled to support multiple radio buttons:
#uncheckAll {
display: none;
}
#uncheckAll:checked ~ * label[for="uncheckAll"] {
display: none;
}
label {
cursor: pointer;
}
label:not([for]) {
position: relative;
}
label[for="uncheckAll"] {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
input[name="group1"]:not(:checked) + label[for="uncheckAll"] {
display: none;
}
_x000D_
<input type="radio" name="group1" id="uncheckAll" checked="checked" />
<label>
<input type="radio" name="group1" id="radio2" />
<label for="uncheckAll"></label>
You can toggle me on and off!
</label>
<label>
<input type="radio" name="group1" id="radio3" />
<label for="uncheckAll"></label>
And me!
</label>
<label>
<input type="radio" name="group1" id="aragorn" />
<label for="uncheckAll"></label>
And my sword!
</label>
<label>
<input type="radio" name="group1" id="gimli" />
<label for="uncheckAll"></label>
And my axe!
</label>
_x000D_
Wrapped up in a plugin
Limitations:
(function($) {_x000D_
$.fn.uncheckableRadio = function() {_x000D_
var $root = this;_x000D_
$root.each(function() {_x000D_
var $radio = $(this);_x000D_
if ($radio.prop('checked')) {_x000D_
$radio.data('checked', true);_x000D_
} else {_x000D_
$radio.data('checked', false);_x000D_
}_x000D_
_x000D_
$radio.click(function() {_x000D_
var $this = $(this);_x000D_
if ($this.data('checked')) {_x000D_
$this.prop('checked', false);_x000D_
$this.data('checked', false);_x000D_
$this.trigger('change');_x000D_
} else {_x000D_
$this.data('checked', true);_x000D_
$this.closest('form').find('[name="' + $this.prop('name') + '"]').not($this).data('checked', false);_x000D_
}_x000D_
});_x000D_
});_x000D_
return $root;_x000D_
};_x000D_
}(jQuery));_x000D_
_x000D_
$('[type=radio]').uncheckableRadio();_x000D_
$('button').click(function() {_x000D_
$('[value=V2]').prop('checked', true).trigger('change').trigger('click');_x000D_
});
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>_x000D_
<form>_x000D_
<label><input name="myRadio" type="radio" value="V1" /> R1</label>_x000D_
<label><input name="myRadio" type="radio" value="V2" /> R2</label>_x000D_
<label><input name="myRadio" type="radio" value="V3" /> R3</label>_x000D_
<button type="button">Change R2</button>_x000D_
</form>
_x000D_
You could use the checked
property of a radio button to uncheck it.
Something like this:
<script>
function uncheck()
{
document.getElementById('myRadio').checked = false;
}
function check()
{
document.getElementById('myRadio').checked = true;
}
</script>
<input id="myRadio" type="radio" checked="checked"/>
<button onclick="uncheck();">Uncheck</button>
<button onclick="check();">Check</button>
?See it in action here: http://jsfiddle.net/wgYNa/
If you use Iclick pluging, it is as simply as you see below.
$('#radio1').iCheck('uncheck');
In the radio button object creation code include these three lines:
obj.check2 = false; // add 'check2', a user-defined object property
obj.onmouseup = function() { this.check2 = this.checked };
obj.onclick = function() { this.checked = !this.check2 };
As radio button mostly used in group, its a lot easier to grab them by getElementsByName( ' ' );
in your script tag. This will return an array, put an event listener on each array child and set the check state. Look at this sample.
var myRadios = document.getElementsByName('subscribe');
var setCheck;
var x = 0;
for(x = 0; x < myRadios.length; x++){
myRadios[x].onclick = function(){
if(setCheck != this){
setCheck = this;
}else{
this.checked = false;
setCheck = null;
}
};
}
This guide explain how the code works with a visual demonstration.
Here is the way for plain JS, which onchange
and onclick
events are combined (onchange
for checking while onclick
for unchecking).
document.querySelector("input").onchange = function() {
this.onclick = function() {
this.checked = false;
this.onclick = null;
}
};
Most of the modern day browsers consider checked="anything"
as checked="true"
.
You might have to remove the checked attribute if that makes sense in your case, one of which might be related to when you load the page.
$(this).removeAttr('checked')
This might help you in cases when you want your radio button to be checked adhering to some condition. You can simply remove the attribute to achieve that.
PS: Not helpful in all the cases.
That's what I came to:
function uncheck_radio_before_click(radio) {
if(radio.prop('checked'))
radio.one('click', function(){ radio.prop('checked', false); } );
}
$('body').on('mouseup', 'input[type="radio"]', function(){
var radio=$(this);
uncheck_radio_before_click(radio);
})
$('body').on('mouseup', 'label', function(){
var label=$(this);
var radio;
if(label.attr('for'))
radio=$('#'+label.attr('for')).filter('input[type="radio"]');
else
radio=label.children('input[type="radio"]');
if(radio.length)
uncheck_radio_before_click(radio);
})
Source: Stackoverflow.com