问题
I have a dynamically generated form with groups of checkboxes representing categories of companies. These eventually get plotted on a dynamic chart (not shown here). Each group of companies has a toggle button to turn all the checkboxes on or off in each category.
I have a jQuery handler for the first toggle button (Tech Giants) using its ID and then checks or unchecks all the boxes in that group accordingly.
My question is this, which refers to the last portion of code in the block below. Instead of manually coding a handler for each toggle button, how can I create one that will apply to all of them on the page? Each button should only check or uncheck all the boxes in its specific category. Note that the first button on the page is separate, and not part of the category selection checkboxes we want to handle.
Here's the code in JSFiddle: https://jsfiddle.net/gq5tw309/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- This button is different than the other buttons -->
<button class="button-text" id="customize-button">Open User Settings</button>
<!-- Placeholder for dynamic form -->
<div id="company-selection-form"></div>
<script type="text/javascript">
function toMachineString(humanString) {
var machineString = humanString.replace(/\s+/g, '-').toLowerCase();
machineString = machineString.replace('&','');
return machineString;
}
// Setup the form
var categories = new Map([
['Tech Giants',['Alphabet','Amazon','Apple','Facebook','Microsoft']],
['Semiconductors', ['AMD','Intel','Nvidia']],
['Telecoms',['AT&T','Verizon','Sprint','T-Mobile']]
// ...
]);
// Build company selection form inputs
let companySelectionHTML = '';
for (let category of categories) {
categoryName = category[0];
categoryList = category[1];
// Setup a div to differentiate each category of companies.
// Will be used for turning on/off categories en masse
companySelectionHTML += `<div id="${toMachineString(categoryName)}">\n`;
// Category heading
companySelectionHTML += `<h4>${categoryName}</h4><button id="btn-${toMachineString(categoryName)}" data-checked="true">Toggle</button>`;
categoryList.forEach(companyName => {
companySelectionHTML += `
<label class="checkbox-label">
<input id="x-${toMachineString(companyName)}" class="checkbox" type="checkbox" name="company" value="${companyName}" checked>
<label for="x-${toMachineString(companyName)}">${companyName}</label>
</label>`;
});
companySelectionHTML += '</div>\n</div>\n</div>\n';
}
// Append to DOM
const companySelectionId = document.getElementById('company-selection-form');
companySelectionId.insertAdjacentHTML('beforeend', companySelectionHTML);
// Arm the toggle button
// HOW DO I APPLY THIS TO ALL THE TOGGLE BUTTONS INSTEAD OF JUST ONE?
$(document).ready(function(){
$('#tech-giants').click(function() {
// Access the data object of the button
var buttonData = $(this).data();
// Set all checkboxes 'checked' property
$('#tech-giants input[type=checkbox]').prop('checked', !buttonData.checked);
// Set the new 'checked' opposite value to the button's data object
buttonData.checked = !buttonData.checked;
// Update the chart -- code goes here
// dynamically-refresh-chart();
});
});
</script>
Thank you!
回答1:
You could do it like this: bind the click()
event to all buttons that have an id
starting with "btn" $(document).on("click", "button[id^='btn']", function() {});
or just add a class to all toggle buttons and bind the click()
event to them, which I did in the following code.
function toMachineString(humanString) {
var machineString = humanString.replace(/\s+/g, '-').toLowerCase();
machineString = machineString.replace('&', '');
return machineString;
}
// Setup the form
var categories = new Map([
['Tech Giants', ['Alphabet', 'Amazon', 'Apple', 'Facebook', 'Microsoft']],
['Semiconductors', ['AMD', 'Intel', 'Nvidia']],
['Telecoms', ['AT&T', 'Verizon', 'Sprint', 'T-Mobile']]
// ...
]);
// Build company selection form inputs
let companySelectionHTML = '';
for (let category of categories) {
categoryName = category[0];
categoryList = category[1];
// Setup a div to differentiate each category of companies.
// Will be used for turning on/off categories en masse
companySelectionHTML += `<div id="${toMachineString(categoryName)}">\n`;
// Category heading
companySelectionHTML += `<h4>${categoryName}</h4><button id="btn-${toMachineString(categoryName)}" class="category" data-checked="true">Toggle</button>`;
categoryList.forEach(companyName => {
companySelectionHTML += `
<label class="checkbox-label">
<input id="x-${toMachineString(companyName)}" class="checkbox" type="checkbox" name="company" value="${companyName}" checked>
<label for="x-${toMachineString(companyName)}">${companyName}</label>
</label>`;
});
companySelectionHTML += '</div>\n</div>\n</div>\n';
}
// Append to DOM
const companySelectionId = document.getElementById('company-selection-form');
companySelectionId.insertAdjacentHTML('beforeend', companySelectionHTML);
$(document).ready(function() {
$(document).on("click", ".category", function() {
var buttonData = $(this).data();
$(this).closest("div").find('input[type=checkbox]').prop('checked', !buttonData.checked);
buttonData.checked = !buttonData.checked;
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="button-text" id="customize-button">Open User Settings</button>
<div id="company-selection-form"></div>
回答2:
First bind your event like so for dynamically generated HTML (the buttons):
$('body').on("click", ".yourClass", function () {
//Your code goes here
});
Then use the class on the button instead of an ID, to apply the event listener to all buttons with the given class.
来源:https://stackoverflow.com/questions/62286655/adding-event-handler-to-many-dynamically-generated-buttons-with-jquery