Checking and unchecking a checkbox with JavaScript: a quick lesson on HTML IDL attributes
Tags: javascript, html, codesnippets, todayilearned
Published: 2023-01-06 13:26:55

---
title: "Checking and unchecking a checkbox with JavaScript: a quick lesson on HTML IDL attributes"
published: true
description: "A snippet to check and uncheck an HTML checkbox with vanilla JavaScript. Plus an introduction to content attributes versus IDL attributes on HTML elements."
tags: JavaScript, HTML, CodeSnippets, TodayILearned
canonical_url: https://aileenrae.co.uk/blog/programatically-check-uncheck-checkbox-javascript
---

I feel like an idiot for this amount of time I spent on this one today at work.

**TL:DR;** What you're looking for is:

```js
// <input type="checkbox" id="your-checkbox-id" />
const yourCheckbox = document.getElementById('your-checkbox-id');

// check the checkbox
yourCheckbox.checked = true;

// uncheck the checkbox
yourCheckbox.checked = false;
```

So what was I doing wrong today? Let's take a look at the Codepen below.

{% codepen https://codepen.io/aileen-r/pen/abjmNwP %}

## ❌ Using the setAttribute method

I had a list of checkboxes, with one "select all" checkbox at the top. When the "select all" checkbox is checked, I wanted to check all the underlying checkboxes.

I tried setting the `checked` attribute on the input elements. My code looked something like this:

```js
const selectAllCheckbox = document.getElementById('select-all');
const childCheckboxes = document.querySelectorAll('.child-checkbox');

const toggleSelectAllCheckbox = () => {
  const areAllChecked = [...childCheckboxes].every(c => c.hasAttribute('checked'));
  if (areAllChecked) {
    // uncheck all if every checkbox is checked
    childCheckboxes.forEach(c => {
      c.removeAttribute('checked');
    })
  }
  else {
    // otherwise, check all
    childCheckboxes.forEach(c => {
      c.setAttribute('checked', '');
    })
  }
}

selectAllCheckbox.addEventListener('click', toggleSelectAllCheckbox);
```

This seems alright at first glance. If you toggle the "select all" checkbox it works.

However, if you toggle any of the child checkboxes _then_ toggle "select all", it ignores the children you just toggled. Try it out in the Codepen example above. This won't do.

## ✅ Setting the "checked" property

Eventually, I figured out using the `setAttribute()` and `removeAttribute()` methods was where I was going wrong. Instead, I needed to access and set the `checked` property directly, like so:

```js
const selectAllCheckbox = document.getElementById('select-all');
const childCheckboxes = document.querySelectorAll('.child-checkbox');

const toggleSelectAllCheckbox = () => {
  const areAllChecked = [...childCheckboxes].every(c => c.checked === true)
  childCheckboxes.forEach(c => {
    c.checked = !areAllChecked;
  })
}

selectAllCheckbox.addEventListener('click', toggleSelectAllCheckbox);
```

There is some extra work to make sure the "select all" checkbox updates when toggling the children, but you can check out the [Codepen](https://codepen.io/aileen-r/pen/abjmNwP) for that.

## Why was I wrong?

When it comes to setting attributes on HTML elements, I had always assumed `element.setAttribute('attribute', value)` was roughly interchangeable with `element.attribute = value`. But there is a subtle difference.

HTML attributes have two sides, the **content attribute** and the **<abbr title="Interface Description Language">IDL</abbr> attribute**.

The **content attribute** is what is written in HTML. It is also accessed via the methods `element.hasAttribute()`, `element.getAttribute()`, `element.setAttribute()`, and `element.removeAttribute()`.

For example, if I have `<input type="checkbox" id="your-checkbox-id" />`, `checkboxElement.hasAttribute('checked')` will be false.

If I then set `checkboxElement.setAttribute('checked')` and use a devtools inspector, my HTML will now be `<input type="checkbox" id="your-checkbox-id" checked />`.

![Screenshot of a checkbox element in Firefox devtools inspector.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a7pf3vebgvm1kfirg05i.png)

The **IDL attribute** is a JavaScript property. If I log my element to the console with `console.log('checkboxElement')`, I can drill into it like any JavaScript object and see all the properites. These are the IDL attributes.

![Screenshot of a checkbox element logged to the Firefox developer console. A list of properties, including "checked" are visible.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bgcvkrb1pb1zos9hg3rc.png)

The IDL attribute will use the underlying content attribute. `element.setAttribute("attribute", value)` and `element.attribute = value` are interchangable...most of the time.

The catch with checkboxes is that, for the `checked` IDL attribute, the underlying content attribute is *not* `checked`. It doesn't have one.

The content attribute `checked` for inputs with `type="checkbox"` instead corresponds to the `defaultChecked` IDL attribute. Even though `element.setAttribute("checked")` *sort of* works for programatically checking a checkbox (at least in the browsers I tried), it's not supposed to.

Use the `checked` content attribute if you want the checkbox checked by default at page load (or when the element is first painted).

If you want to mutate the checkbox with JavaScript, use the `checked` IDL attribute: `element.checked = true`.

## Sources
MDN: [\<input type="checkbox"\>](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox), [IDL glossary entry](https://developer.mozilla.org/en-US/docs/Glossary/IDL).