DEV Community

Latz
Latz

Posted on • Edited on

The modern way of checking radio groups

Checking radio groups in JavaScript has always been a bit tricky because you can only check if a particular radio button is selected, not the whole group at once.

<input type="radio" name="fruits" id="banana" checked="checked" />Banana
<input type="radio" name="fruits" id="apple" />Apple
<input type="radio" name="fruits" id="cherry" />Cherry
Enter fullscreen mode Exit fullscreen mode

Wow, that looks archaic. There must be a better way using the new ES6 features, and there is! As of ES2015, NodeList contains a forEach method(). This makes things much easier:

var fruits = document.getElementsByName('fruits');
let selectedFruit = '';
fruits.forEach((fruit) => {
  if (fruit.checked) {
    selectedFruit = fruit.id;
  }
});
Enter fullscreen mode Exit fullscreen mode

Still a lot of lines. We can make the code much tighter, but also much more unreadable:

[document.getElementsByName('fruits')].some(
  (fruit) => (let selectedFruit = fruit.id) && fruit.checked
);
Enter fullscreen mode Exit fullscreen mode

This requires a bit of explanation, because in order to achieve it we have to dig deep into our bag of tricks.

First we convert the NodeList to an array using the spread operator to have all the funky Array() methods available.
The Array() method we use is some(). This method loops over an array until the callback function returns true. In our case we exit the loop by checking for “fruit.checked” which is true if the radio button is checked.

The second trick is to include the assignment of the loop variable fruit to the upper scope variable selectedFruit. This assignment always returns true, and therefore does not affect the result of the whole statement when it’s linked with && operator to the other comparison.

BTW, we don’t need to declare an upper scope variable any more here because we don’t enter a new scope in the callback function. New scopes require curly braces which we don’t need here because the callback function only contains a single statement.
You can be picky and point our that selectedFruit is undeclared, but the code works nevertheless. So what?

Conclusion
We reduced the code from six lines to three and from 193 to 115 characters. Not bad and your code will look much cooler on GitHub!

Top comments (2)

Collapse
 
jonrandy profile image
Jon Randy 🎖️ • Edited

Shorter:

let selectedFruit = [...document.getElementsByName('fruits')].find(({checked}) => checked)?.id
Enter fullscreen mode Exit fullscreen mode

Shorter still (but will only get you the item that is initially checked):

let selectedFruit = document.querySelector('[name=fruits][checked]')?.id
Enter fullscreen mode Exit fullscreen mode
Collapse
 
latz profile image
Latz

Thank you! Very smart solution. I would have never thought of that, perhaps because I was mentally fixed to use an explicit loop.