I have this scheme for multiselection of checkboxes, and I need p.label
to trigger the .item
checkbox (child of it);
But my JS script is working only when .labels
are clicked, it selects/unselects the checkboxes, but when I click directly on the checkboxes inputs, I need that the checkboxes have the normal behavior of a checkbox, and ignore the onclick
event added to all labels.
In short: I need the items in the list to be selectable through the label or directly in the box. How can I a fix my script to prevent colisions that are happening?
let fruits_labels = document.querySelectorAll("#fruits .label");
let fruits_items = document.querySelectorAll("#fruits .label .item");
fruits_labels.forEach((label, index) => {
label.onclick = (event) => {
console.log("index: " + index);
fruits_items[index].checked = (fruits_items[index].checked == true) ? false : true;
}
});
let colors_labels = document.querySelectorAll("#colors .label");
let colors_items = document.querySelectorAll("#colors .label .item");
colors_labels.forEach((label, index) => {
label.onclick = (event) => {
console.log("index: " + index);
colors_items[index].checked = (colors_items[index].checked == true) ? false : true;
}
});
div.container{ margin: 0; padding: 0; margin-bottom: 10px; width: 200px; border: 1px solid black; }
div.container p.label { margin: 0; padding: 4px 8px; display: flex; align-items: center; border: 1px solid magenta; }
div.container p.label:hover { background-color: yellow; }
div.container p.label input[type=checkbox].item{ margin-right: 6px; }
<div class="container" id="fruits">
<p class="label"><input class="item" type="checkbox">APPLE</p>
<p class="label"><input class="item" type="checkbox">BANANA</p>
<p class="label"><input class="item" type="checkbox">KIWI</p>
<p class="label"><input class="item" type="checkbox">LEMON</p>
<p class="label"><input class="item" type="checkbox">ORANGE</p>
</div>
<div class="container" id="colors">
<p class="label"><input class="item" type="checkbox">RED</p>
<p class="label"><input class="item" type="checkbox">GREEN</p>
<p class="label"><input class="item" type="checkbox">BLUE</p>
</div>
2
Answers
Don’t re-invent the wheel. Your desired behaviour can be achieved natively with a
<label>
element:If you, for some reason can’t use the above, another option would be to check the
firstChild
of the click’sevent.target
. If that’s acheckbox
, you’ll need to toggle it:While you could use labels and they would work nicely, as Ostone0 described, I will show you how your script can be fixed, so you will learn about propagation and
stopPropagation
, but you should not overcomplicate yourself and you should aim to simplify your code once your tests work.Events are bubbling, that is, the event of a tag propagates an event to its parent which propagates one to its parent and so on. So, when you click on the checkbox, then its default click handler changes the
checked
value and propagates to the parent, which has an event that negates thechecked
value. So, you can usestopPropagation
to avoid the bubbling from happening.