You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 04:06:26