-1

I'm trying to log the checked property of a radio element on click event. But It returns the wrong value.

const radio = document.querySelector('input[type=radio]')
radio.addEventListener('click', (ev) => {
  ev.preventDefault();
  console.log(ev.target.checked);
})
<p class="rInput">
  <input type="radio" name="R" id="ID">
  <label for="ID">The label</label>
</p>

When clicking on the radio it should log the checked status but it always logs true.

My solution to this was adding a timeOut of 0 millisecond, and it worked

const radio = document.querySelector('input[type=radio]')
radio.addEventListener('click', (ev) => {
  ev.preventDefault();
  setTimeout(() => {
    console.log(ev.target.checked);
  }, 0);
})
<p class="rInput">
  <input type="radio" id="ID">
  <label for="ID">The label</label>
</p>

But what is the problem and why this happens? Is there a better solution?

Kia Abdi
  • 77
  • 1
  • 6
  • There are only two events available on radio buttons i.e `change` and `input`. Why in the first place are you using `click` event on `radio` buttons? [READ](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio) – DecPK Sep 12 '21 at 14:34
  • 1
    If the radio input is checked it will always be true. Do you have other radio inputs, or did you mean to use a checkbox? – Andy Sep 12 '21 at 14:34
  • @pilchard It started as unchecked radio and I'm using `preventDefault` to prevent it from changing it to `checked` so I could log `false` as result. – Kia Abdi Sep 12 '21 at 14:41
  • @Andy I'm preventing it from being checked by click – Kia Abdi Sep 12 '21 at 14:49

2 Answers2

0

Ok so this is a bit of a weird question. Let me go try to explain why I call it a weird question:

  1. You are setting a preventDefault on a radio button which would remove it's default properties (radio buttons are not the same input forms as regular buttons). The reason for that is that a regular button can have multiple states whereas Radio button have only 2 states namely- True & False.
  2. You are checking only if the button isChecked by using console.log(rI.checked); therefore you will always log TRUE.

I hope that makes sense. As a follow up, I think you should CHECK out (pun intended) how to make a button unchecked. This here is a great answer on how to do it using JS without any frameworks.

UPDATED Code Snippet:

$(document).ready(function(){
    $('input[type="radio"]').click(function(){
        if($(this).prop("checked") === true){
            console.log("Checkbox is checked.");
        }
        else if($(this).prop("checked") === false){
            console.log("Checkbox is unchecked.");
        }
    });
});
ZombieChowder
  • 1,187
  • 12
  • 36
  • I'm using preventDefault on `click` event to prevent it from checking the radio button. and logging the `ev.target.checked` anyways (true or false), but the answer is always `true` even though It's actually unchecked and should return false. – Kia Abdi Sep 12 '21 at 14:48
  • @KiaAbdi Read the link I've given you at the bottom of my answer. It's always true because you don't uncheck it. Also try running the code I've updated my answer with so you can see for yourself. – ZombieChowder Sep 12 '21 at 14:56
  • I read the link you provided but I can't find the problem. The radio initiated as unchecked, I even tried unchecking it before adding the event listener using `radio.checked = false;` but still, It gives the wrong result. I checked it with your code (I added preventDefault). and again... wrong result – Kia Abdi Sep 12 '21 at 15:11
  • 1
    I think the answer to what @KiaAbdi was asking about to explain the 0s timeout requirement has to do with the fact that JavaScript is a single-threaded non-blocking I/O language. On a high level, when you tick the checkbox the execution pipeline might look like this: (1) click event sets `checked` property to true, (2) `console.log()`, (3) `preventDefault()` resets `checked` property back to false. By adding 0s timeout (which is 0.004s in reality), you switch the execution order of (2) and (3). – thdoan May 20 '23 at 20:11
  • A good article on this topic if you want to get into the nitty gritty: https://www.geekabyte.io/2014/01/javascript-effect-of-setting-settimeout.html – thdoan May 20 '23 at 20:11
0

It would be simpler to just disable the radio button you don't want clicked.

const radios = document.querySelectorAll('input[type="radio"]');
radios.forEach(radio => radio.addEventListener('click', handleClick, false));

function handleClick(e) {
  const { id, checked } = e.target;
  console.log(id, checked);
};
<div>
  <label for="1">First
    <input name="radio" id="1" type="radio">
  </label>
  <label for="2">Second (disabled)
    <input name="radio" id="2" type="radio" disabled>
  </label>
  <label for="3">Last
    <input name="radio" id="3" type="radio">
  </label>
</div>
Andy
  • 61,948
  • 13
  • 68
  • 95
  • I'm trying to perform some actions if the radio is unchecked. and change it to `checked` later if needed. and if it's already checked ignore the click event. so I need to know the `checked` status for the radio input – Kia Abdi Sep 12 '21 at 14:58