列表行内Checkbox监听事件未触发,仅首个Checkbox生效问题
The issue you're facing stems from two critical mistakes in your JavaScript code:
document.querySelectoronly targets the first matching element: This is why only your first checkbox works—you’re attaching the event listener to just that single element, not all checkboxes in your list.- Incorrect selector: Your code uses
.input[type="checkbox"], which looks for elements with a class ofinput, but your checkboxes don’t have this class. The correct selector isinput[type="checkbox"].
Here are two reliable solutions to resolve this:
Solution 1: Attach Listeners to All Checkboxes (Vanilla JS + jQuery)
This approach selects every checkbox and adds a change listener to each one. It’s ideal if your list is rendered once when the page loads:
document.addEventListener('DOMContentLoaded', function () { // Get all checkbox elements (fixed selector) const checkboxes = document.querySelectorAll('input[type="checkbox"]'); // Loop through each checkbox to attach the listener checkboxes.forEach(checkbox => { checkbox.addEventListener('change', function () { const list_id = $(this).attr('list_id'); const isActive = this.checked; // Send AJAX request to your Flask app $.ajax({ url: '/dashboard', type: 'POST', data: { id: list_id, active: isActive ? 'true' : 'false' } }) .done(response => console.log('Update successful:', response)) .fail(error => console.error('Update failed:', error)); console.log(`ID: ${list_id}, Active: ${isActive}`); }); }); });
Solution 2: Event Delegation (Best for Dynamic Content)
If your list might be updated dynamically (e.g., loaded via AJAX after the initial page load), use event delegation. This attaches a single listener to a parent container, which catches events from all child checkboxes—even those added later:
First, wrap your checkboxes in a parent container (add a class like checkbox-container to the parent div in your Jinja2 template):
<div class="checkbox-container"> {% for row in list %} <label> Off <input name="active{{ row.id }}" id="active{{ row.id }}" type="checkbox" list_id="{{ row.id }}"> <span class="lever"></span> On </label> {% endfor %} </div>
Then use this JavaScript:
$(document).ready(function() { // Attach listener to the parent container instead of individual checkboxes $('.checkbox-container').on('change', 'input[type="checkbox"]', function() { const list_id = $(this).attr('list_id'); const isActive = $(this).is(':checked'); $.ajax({ url: '/dashboard', type: 'POST', data: { id: list_id, active: isActive.toString() } }); console.log(`ID: ${list_id}, Active: ${isActive}`); }); });
Key Tips:
- Avoid closure bugs: Using
forEach(instead of a traditionalforloop) ensures each listener has access to the correct checkbox element. - Data consistency: Sending
activeas a string ('true'/'false') matches your original code, but you could also send a boolean directly—Flask will parse it correctly if you userequest.get_json()instead ofrequest.form. - Debugging: Add
.done()and.fail()callbacks to your AJAX requests to catch any errors with the POST call.
内容的提问来源于stack exchange,提问作者mntnrk

