如何在HTML foreach循环中向jQuery传递元素ID?
解决循环中Bootstrap Switch开关仅第一个生效的问题
问题根源是你在foreach循环里重复使用了相同的ID(比如toggleForm、customSwitch1、id、statusText),而HTML规范里ID必须是唯一的,所以jQuery的ID选择器只会匹配到页面中第一个出现的元素,导致后面的开关都无法正常工作。下面是具体的修复方案:
第一步:修改HTML循环代码
把所有重复的ID替换成类,同时用data-*属性存储用户ID和状态,确保每行元素能被独立识别:
@foreach($details as $detail) <tr> <td>{{$detail['id']}}</td> <td>{{$detail['name']}}</td> <td>{{$detail['type']}}</td> <td>{{$detail['email']}}</td> <td><img src="{{asset('/admin/images/avatars/'.$detail['image'])}}"></td> <td>{{$detail['mobile']}}</td> <td> <form method="post" class="toggleForm"> <fieldset> <div class="form-group"> <div class="custom-control custom-switch"> <!-- 替换ID为类,添加data属性存储用户信息 --> <input type="checkbox" class="custom-control-input customSwitch" name='machine_state' id="customSwitch-{{$detail['id']}}" data-id="{{$detail['id']}}" data-status="{{$detail['status']}}"> <!-- 隐藏域替换为类 --> <input type="hidden" class="userId" value="{{$detail['id']}}" > <!-- 状态文本替换为类,label的for属性关联对应checkbox --> <label class="custom-control-label statusText" for="customSwitch-{{$detail['id']}}"> </label> <!-- 提示元素替换为类 --> <little class="littleupdate"></little> </div> </div> </fieldset> </form> </td> </tr> @endforeach
第二步:重构jQuery代码
不再依赖ID选择器,而是通过事件触发的元素上下文($(this))定位当前行的相关元素,实现每个开关独立处理:
// 初始化所有开关的状态 function initStatus() { $('.customSwitch').each(function() { var $currentSwitch = $(this); var userId = $currentSwitch.data('id'); var initialStatus = $currentSwitch.data('status'); // 根据初始状态设置开关和文本,如需从后端同步状态可保留下方AJAX逻辑 if (initialStatus == 1) { $currentSwitch.prop('checked', true); updateStatusText($currentSwitch, 1); } else { $currentSwitch.prop('checked', false); updateStatusText($currentSwitch, 0); } /* // 如需从后端拉取最新状态,取消注释这段代码 $.ajax({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }, type: "post", url: "/admin/check-status", data: {id : userId}, success: function (result) { if (result == "true") { $currentSwitch.prop('checked', true); updateStatusText($currentSwitch, 1); } else { $currentSwitch.prop('checked', false); updateStatusText($currentSwitch, 0); } } }); */ }); } // 更新当前开关对应的状态文本 function updateStatusText($switch, status_val) { var statusStr = status_val == 1 ? "Active" : "Inactive"; $switch.closest('.custom-switch').find('.statusText').text(statusStr); } // 绑定开关切换事件 function bindToggleEvent() { // 事件委托确保动态生成的元素也能触发事件 $(document).on('change', '.customSwitch', function() { var $currentSwitch = $(this); var statusVal = $currentSwitch.is(':checked') ? 1 : 0; updateStatus($currentSwitch, statusVal); }); } // 向后端提交状态更新请求 function updateStatus($switch, status_val) { var userId = $switch.data('id'); var $updateTip = $switch.closest('.custom-switch').find('.littleupdate'); $.ajax({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') }, type: "POST", url: "/admin/set-status", data: {status: status_val, id: userId}, success: function (result) { if(result == "true") { updateStatusText($switch, status_val); } else { // 更新失败,还原开关状态并提示 $switch.prop('checked', !$switch.is(':checked')); $updateTip.html("<font color='red'> - Error while updating!</font>").fadeIn(0).fadeOut(1500); } }, error:function (){ // 请求失败,还原开关状态并提示 $switch.prop('checked', !$switch.is(':checked')); $updateTip.html("<font color='red'> - Request failed!</font>").fadeIn(0).fadeOut(1500); } }); } // 页面加载完成后初始化 $(document).ready(function () { initStatus(); bindToggleEvent(); });
关键修改说明
- 替换ID为类:避免重复ID导致的选择器冲突,类支持重复使用,适配循环生成的元素场景。
- 使用
data-*属性:直接存储用户ID和状态,无需额外查找隐藏域,获取数据更高效。 - 基于上下文查找元素:通过
$(this)定位当前触发事件的开关,再用.closest()、.find()遍历DOM,确保操作的是当前用户对应的组件。 - 事件委托:用
$(document).on()绑定事件,确保动态生成的开关也能正常触发切换逻辑。
内容的提问来源于stack exchange,提问作者Orkhan Orkhan
相关产品推荐
相关产品推荐

