如何实现点击按钮动态添加卡片及卡片内选项功能
修复动态添加选项与卡片的功能问题
我看了你当前的代码,发现几个细节问题导致动态添加的功能没正常跑起来,咱们直接来修复并优化这个实现:
先说说原代码里的核心问题
- jQuery选择器漏了类名前缀:比如
$("addMore")应该写成$(".addMore"),不然找不到对应的元素 - 重复绑定事件:在添加卡片的点击事件里又嵌套了
$(document).ready(),这会导致事件被多次绑定,触发一次可能执行多次逻辑 - 移除卡片的DOM层级判断错误:原代码里
$(this).parent().remove()只会删掉输入框和Remove按钮所在的小容器,而不是整张卡片 - 表单name属性设计不合理:问题输入框没有name,选项的name统一用
name[]会导致后端无法区分属于哪个问题的选项
修正后的完整代码
HTML部分
<body> <form method="post" action=""> <div class="cardBox"> <!-- 初始卡片模板 --> <div class="block"> <div class="card"> <div style="display: flex; gap: 8px; margin-bottom: 12px;"> <input type="text" name="questions[]" class="form-control" placeholder="Enter Your Question"/> <span class="removeCard" style="cursor: pointer; color: #dc3545;">Remove</span> </div> <!-- 选项组容器 --> <div class="optionsContainer"> <div class="form-group fieldGroup"> <div class="input-group" style="gap: 8px;"> <input type="text" name="options[0][]" class="form-control" placeholder="Enter Option"/> <a href="javascript:void(0)" class="btn btn-success addMore"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add Option </a> </div> </div> </div> <!-- 隐藏的选项模板 --> <div class="form-group fieldGroupCopy" style="display: none;"> <div class="input-group" style="gap: 8px; margin-top: 8px;"> <input type="text" class="form-control" placeholder="Enter Option"/> <a href="javascript:void(0)" class="btn btn-danger remove"> <span class="glyphicon glyphicon-remove" aria-hidden="true"></span> Remove </a> </div> </div> </div> </div> </div> <span class="add" style="cursor: pointer; color: #28a745; margin-top: 16px; display: inline-block;">ADD NEW CARD</span> </form> </body> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
JavaScript部分
$(document).ready(function(){ const maxGroup = 50; // 动态添加选项到当前卡片 $(document).on("click", ".addMore", function(){ const $card = $(this).closest('.card'); const $fieldGroups = $card.find('.fieldGroup'); if($fieldGroups.length < maxGroup){ // 克隆隐藏的模板,注意要重置name属性 const fieldHTML = $('.fieldGroupCopy').clone().removeClass('fieldGroupCopy').show(); // 给新选项设置对应的name,匹配当前卡片的索引 const cardIndex = $card.closest('.block').index(); fieldHTML.find('input').attr('name', `options[${cardIndex}][]`); $card.find('.optionsContainer').append(fieldHTML); }else{ alert(`Maximum ${maxGroup} options are allowed per card.`); } }); // 移除单个选项 $(document).on("click", ".remove", function(){ $(this).closest('.fieldGroup').remove(); }); // 动态添加整张卡片 $('.add').click(function(){ const $lastBlock = $('.block:last'); const newCardIndex = $lastBlock.index() + 1; // 克隆初始的卡片模板 const $newBlock = $lastBlock.clone(); // 清空输入框内容 $newBlock.find('input').val(''); // 更新问题输入框的name $newBlock.find('[name^="questions"]').attr('name', 'questions[]'); // 更新选项输入框的name,匹配新卡片的索引 $newBlock.find('[name^="options"]').attr('name', `options[${newCardIndex}][]`); // 插入到最后 $('.cardBox').append($newBlock); }); // 移除整张卡片 $('.cardBox').on('click','.removeCard',function(){ // 确保至少保留一张卡片 if($('.block').length > 1){ $(this).closest('.block').remove(); // 移除后重新更新所有选项的name索引,保证后端接收的数组连续 $('.block').each(function(index){ $(this).find('[name^="options"]').attr('name', `options[${index}][]`); }); }else{ alert('至少要保留一张卡片哦'); } }); });
关键功能说明
- 选项与卡片的关联:通过
options[cardIndex][]的命名方式,让后端能清晰区分每个问题对应的选项数组 - 事件委托:用
$(document).on()绑定动态生成元素的点击事件,确保新添加的选项和卡片都能触发对应的逻辑 - 卡片移除后的索引修正:删除卡片后重新更新剩余卡片选项的name索引,避免后端接收的数组出现断层
- 输入限制:保留了最多50个选项的限制,同时添加了至少保留一张卡片的提示
内容的提问来源于stack exchange,提问作者Avinash Maddala
相关产品推荐
相关产品推荐

