JQuery动态添加复选框问题:新增主分类下Add Section按钮失效
解决动态生成主分类内「Add Section」按钮失效问题
问题核心原因
你碰到的主要问题是事件绑定时机不匹配:页面加载时用$('.js-add-split').click(...)绑定的事件,只能对当时已存在的按钮生效;而后续通过「Create New Category」动态生成的按钮,并没有被绑定事件。另外还有两个小坑:全局共享的count会导致所有主分类的section计数混乱,以及前端JS模板里不能直接写Razor的@for循环(Razor是服务器端渲染逻辑,JS是客户端执行,动态生成时没法再触发服务器端代码)。
分步解决方案
1. 改用事件委托绑定按钮事件
把事件绑定到页面加载时就存在的静态父元素(比如.sup-content),这样所有后续动态生成的.js-add-split按钮都能触发事件:
// 替换原来的$('.js-add-split').click(...)写法 $('.sup-content').on('click', '.js-add-split', function() { // 后续逻辑写在这里 });
2. 为每个主分类维护独立的section计数
不要用全局count变量,而是给每个主分类添加数据属性存储当前section数量:
- 初始主分类的
.services__supnisation标签添加data-section-count="1" - 动态生成新主分类时也带上这个属性
3. 提前把服务器端的numOfCheckboxes值传到前端
前端JS里没法执行Razor循环,所以在页面加载时把这个值存在全局变量里:
<!-- 在页面头部添加这段脚本 --> <script> // 从服务器端获取复选框数量计算结果 const numOfCheckboxes = @((int)TempData["Counter"] * 4 - 1); </script>
4. 修正新section的插入位置
确保新section添加到当前点击按钮所在的主分类内,而不是全局的最后一个位置。
修改后的完整代码
初始主分类(添加数据属性)
<div class="services-content sup-content"> <div class="services__supnisation" data-section-count="1"> <!-- 原输入框、复选框区域代码不变 --> <div class="services-actions"> <button type="button" class="mdl-button secondary-btn secondary-btn-border add-split-btn js-add-split mdl-js-button mdl-js-ripple-effect"> Add Section </button> </div> </div> <!-- New Category should be added here --> </div>
「Create New Category」按钮的JS代码(修正计数与HTML生成逻辑)
$('.js-create-sup').click(function () { // 计算新主分类的ID const categoryCount = $('.services__supnisation').length + 1; // 前端生成复选框HTML let checkboxesHtml = ''; for (let j = 1; j <= numOfCheckboxes; j++) { checkboxesHtml += ` <li> <input type="checkbox" id="sup-${j}-${categoryCount}"> <label for="sup-${j}-${categoryCount}"><i class="icon-tick" disabled></i></label> </li> `; } // 组装新主分类的HTML const supContent = ` <div class="services__supnisation" data-section-count="1"> <div class="services__supnisation-title"> <input type="text" id="sup-title-${categoryCount}" class="sup-title js-sup-title" value="sup ${categoryCount}"> </div> <div class="services-item js-splits-item"> <ul>${checkboxesHtml}</ul> <div class="services-item__footer"> <small class="services-item__availability"> <span class="title">Section 1</span> </small> </div> </div> <div class="services-actions"> <button type="button" class="mdl-button secondary-btn secondary-btn-border add-split-btn js-add-split mdl-js-button mdl-js-ripple-effect"> Add Section </button> </div> </div> `; // 插入到最后一个主分类后面 $(supContent).insertAfter($('.sup-content .services__supnisation').last()); });
「Add Section」按钮的完整事件代码
// 提前从服务器端获取的复选框数量 const numOfCheckboxes = @((int)TempData["Counter"] * 4 - 1); $('.sup-content').on('click', '.js-add-split', function() { // 定位当前点击按钮所属的主分类 const $parentCategory = $(this).closest('.services__supnisation'); // 获取并更新当前主分类的section计数 let sectionCount = parseInt($parentCategory.data('section-count')) + 1; $parentCategory.data('section-count', sectionCount); // 提取主分类ID(从输入框ID中拆分) const categoryId = $parentCategory.find('.js-sup-title').attr('id').split('-')[2]; // 生成新section的复选框HTML let checkboxesHtml = ''; for (let j = 1; j <= numOfCheckboxes; j++) { checkboxesHtml += ` <li> <input type="checkbox" id="sup-${j}-${categoryId}-${sectionCount}"> <label for="sup-${j}-${categoryId}-${sectionCount}"><i class="icon-tick" disabled></i></label> </li> `; } // 组装新section的HTML const splitContent = ` <div class="services-item js-splits-item"> <ul>${checkboxesHtml}</ul> <div class="services-item__footer"> <small class="services-item__availability"> <span class="title">Section ${sectionCount}</span> </small> </div> </div> `; // 插入到当前主分类内的最后一个section后面 $(splitContent).insertAfter($parentCategory.find('.js-splits-item').last()); // 在这里保留你原有的复选框勾选验证逻辑即可 });
关键改动说明
- 事件委托:通过静态父元素监听点击,确保动态生成的按钮也能触发事件
- 独立计数:每个主分类用
data-section-count存储自己的section数量,避免全局变量冲突 - 客户端生成HTML:把Razor的循环逻辑移到前端JS,解决服务器端代码无法在客户端动态执行的问题
- 精准插入:通过
closest('.services__supnisation')定位当前主分类,确保新section添加到正确位置
内容的提问来源于stack exchange,提问作者ExpertGenie
相关产品推荐
相关产品推荐

