Almost anyone familiar with developing for the Web has worked with events. We use these events to know when things happen in the browser like when a user clicks on something, that they entered data, when the webpage is finished loading or was resized.
Events for user interaction
When a user clicks on a checkbox or radio button the element dispatches aclick
event. When clicking on a radio button this event does not always indicate a value has changed only that the user has clicked on the element. The click
event is also triggered when the user uses their keyboard to select a checkbox or radio button.When the checked state of a checkbox or radio button changes, due to the
click
event, then the change
event is dispatched. The change
is the preferred event to use as an indication that the checked state has changed on an element. Some older browsers dispatch the click
event before the checked state changes so that event is not as reliable as the change
event.The sample code below (and here) displays an appropriate message when the user clicks on the checkbox:
<input id="cb10" type="checkbox" value="10"> Ten<br> <hr> <div id="output"></div> <script> var el = document.getElementById('cb10'); var out = document.getElementById('output'); function changeHandler(event) { if (event.target.checked) { out.textContent = 'Ten is checked.'; } else { out.textContent = 'Ten is not checked.'; } } el.addEventListener('change', changeHandler); </script>
The Javascript will display the message 'Ten is checked.' or 'Ten is not checked.' based on the current state of the checkbox.
The checked
property of an element
The checkbox and radio button DOM elements have a checked
property that indicates the current checked state. The checked
property is a boolean
value.Within your JavaScript you can set the
checked
value and the state of the checkbox or radio button will change.<input id="cb10" type="checkbox" value="10"> Ten<br> <script> var el = document.getElementById('cb10'); el.checked = true; </script>
When you set the
checked
property the DOM is not changed. The checked
attribute is only used to define the initial state of the checked
property.After the DOM is rendered the first time setting the property does not affect the attribute and setting the attribute no longer affects the property.
CSS can use either the property or the attribute
CSS is designed to support both the property value and the attribute by using the:checked
selector and the [checked]
selector.:checked
is based on the property value and [checked]
is based on the existence of the checked
attribute.The following CSS will draw a green box around the checkbox when the
checked
property is set to true
:input:checked { outline: 3px solid green; }
And this CSS will draw a red box around the checkbox when the
checked
attribute exists in the DOM:input[checked] { outline: 3px solid red; }
But avoid the attribute selector
It is best to avoid using the attribute selector since the attribute does not change when the user selects the checkbox. But the:checked
selector does recognize anytime the checked
property has changed. If you want to manage the attribute yourself, then the attribute selector might work for you.
Setting the checked
property does not trigger an event
This is something that is not well understood. But when you set the checked
property in JavaScript an event is not dispatched. Which means that if your code expects to always get an event when the checked
state of an element has changed you will only get the event when the user interacts with the element and not when the JavaScript changes the property.This example shows that setting
element.checked
does not trigger an event. Line 18 sets element.checked
to true
or false
based on the button that was clicked.My solution
I provide two examples below that allow your JavaScript to emulate the events that are sent by default through user interaction.
The first example sends the
click
event. Then the browser automatically sends the change
event. This acts most like the real user interaction.function setChecked(el, state) { el.checked = !state; el.dispatchEvent(new MouseEvent('click')); }
The second example only triggers the
change
event. If if all you are listening for is the change
event then this might be the better option. It is also slightly faster since only one event is dispatched.function setChecked(el, state) { el.checked = state; el.dispatchEvent(new Event('change’)); }
Either example will help to resolve the issue of events not being triggered when setting the
checked
property. But you have to make sure that all code calls the helper function instead of setting the checked
property directly.In this example I use the
setChecked
function and events fire like I expect and want.