I use Bootstrap to design my forms. There is a checkbox and an associated label. My goal is to change the value of the checkbox by clicking on the checkbox and to be able to edit the text of the label by clicking on the label. My problem now is that no matter which element I click on, whether label or checkbox, the same event is always called. However, I would like to separate these events.
I have tried it with different event handlers and I have also removed the for attribute. I assume that the classes "custom-control-input" and "custom-control-label" are hindering me. But I want to keep the styling.
Can anyone tell me what else I can try? I would hate to write new styles and maintain them just because of this one use case.
// CLARIFICATION : I do not want to edit both controls at the same time. When I click on the checkbox, I want the checkbox value to toggle between true and false, and when I click on the label, I want to be able to edit the label text without affecting the checkbox value. So both elements work independently of each other.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.2/js/bootstrap.bundle.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.2/css/bootstrap-reboot.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.2/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.2/css/bootstrap-grid.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/4.6.2/js/bootstrap.min.js"></script>
<script>
$(function() {
$('.examples label').on('click', function(e) {
debugger;
console.log('Listener: Label Clicked');
});
$('.examples input').on('click', function(e) {
console.log('Listener: CheckBox Clicked');
});
});
function onClickLabel(e, label) {
console.log('Label Clicked')
}
function onClickCheckBox(e, cb) {
console.log('CheckBox Clicked')
}
</script>
<div class="examples">
<div class="mb-3">
<h3>Does work, but ugly</h3>
<div>
<input type="checkbox" class="" onClick="onClickCheckBox(event, this)">
<label class="" onClick="onClickLabel(event, this)">Check this custom checkbox</label>
</div>
</div>
<div class="mb-3">
<h3>Always triggers the checkbox</h3>
<div>
<input id="cb1" type="checkbox" class="" onClick="onClickCheckBox(event, this)">
<label for="cb1" class="" onClick="onClickLabel(event, this)">Check this custom checkbox</label>
</div>
</div>
<div class="mb-3">
<h3>Triggers everything</h3>
<div class="custom-control custom-checkbox">
<input id="cb0" type="checkbox" class="custom-control-input" onClick="onClickCheckBox(event, this)">
<label for="cb0" class="custom-control-label" onClick="onClickLabel(event, this)">Check this custom checkbox</label>
</div>
</div>
<div class="mb-3">
<h3>Always triggers the label</h3>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" onClick="onClickCheckBox(event, this)">
<label class="custom-control-label" onClick="onClickLabel(event, this)">Check this custom checkbox</label>
</div>
</div>
</div>
Answers
To achieve the behavior you described, you can use event delegation to handle the click events separately for the checkbox and the label. Additionally, you can wrap the checkbox and label in separate div elements to ensure that the events are triggered independently. Here's how you can modify your HTML and JavaScript:
<div class="examples">
<div class="mb-3">
<h3>Separate events</h3>
<div class="checkbox-wrapper">
<input id="cb1" type="checkbox" class="" onClick="onClickCheckBox(event, this)">
<label for="cb1" class="" onClick="onClickLabel(event, this)">Check this custom checkbox</label>
</div>
</div>
</div>
$(function() {
$('.examples .checkbox-wrapper input[type="checkbox"]').on('click', function(e) {
console.log('Listener: CheckBox Clicked');
});
$('.examples .checkbox-wrapper label').on('click', function(e) {
e.stopPropagation(); // Prevent event from bubbling up to the checkbox
console.log('Listener: Label Clicked');
});
});
function onClickLabel(e, label) {
console.log('Label Clicked');
}
function onClickCheckBox(e, cb) {
console.log('CheckBox Clicked');
}
In this code:
- We wrapped the checkbox and label in a
div
with the classcheckbox-wrapper
. - We used event delegation to attach separate click event handlers to the checkbox and label inside the
.examples
container. - When the checkbox is clicked, the
onClickCheckBox
function is called, and when the label is clicked, theonClickLabel
function is called. - We prevented the click event from bubbling up to the checkbox when the label is clicked using
e.stopPropagation()
in the label click event handler.
This approach ensures that clicking the checkbox and the label triggers separate events and allows them to work independently of each other.