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

Laravel 9中多选select框readonly属性无效的解决方法求助

解决方案

针对你的需求——非管理员用户无法修改多选select但数据仍能正常提交,这里提供两个可行方案:

方案一:CSS+JavaScript阻止交互(保留select外观)

这个方案让select看起来和只读状态一致,同时通过JS阻止所有修改操作,不会影响表单提交。

修改Blade代码:

把原select标签里的readonly条件替换为自定义类:

<div class="form-group">
    <label for="assigned_staffs">{{ trans('cruds.appointment.fields.assigned_staff') }}</label>
    @if(auth()->user()->is_admin)
    <div style="padding-bottom: 4px">
        <span class="btn btn-info btn-xs select-all" style="border-radius: 0">{{ trans('global.select_all') }}</span>
        <span class="btn btn-info btn-xs deselect-all" style="border-radius: 0">{{ trans('global.deselect_all') }}</span>
    </div>
    @endif
    <!-- 添加non-admin-readonly类到select -->
    <select class="form-control select2 {{ $errors->has('assigned_staffs') ? 'is-invalid' : '' }} {{ !auth()->user()->is_admin ? 'non-admin-readonly' : '' }}" name="assigned_staffs[]" id="assigned_staffs" multiple>
        @foreach($assigned_staffs as $id => $assigned_staff)
            <option value="{{ $id }}" {{ (in_array($id, old('assigned_staffs', [])) || $appointment->assigned_staffs->contains($id)) ? 'selected' : '' }}>{{ $assigned_staff }}</option>
        @endforeach
    </select>
    @if($errors->has('assigned_staffs'))
        <div class="invalid-feedback">
            {{ $errors->first('assigned_staffs') }}
        </div>
    @endif
    <span class="help-block">{{ trans('cruds.appointment.fields.assigned_staff_helper') }}</span>
</div>

添加CSS和JavaScript:

在页面底部(或对应的资源文件中)加入以下代码:

/* 让select看起来像只读状态 */
.non-admin-readonly {
    background-color: #e9ecef;
    cursor: default;
}
/* 针对select2组件的样式 */
.non-admin-readonly.select2-container--default .select2-selection--multiple {
    background-color: #e9ecef;
    pointer-events: none;
}
.non-admin-select2-disabled {
    pointer-events: none;
    opacity: 0.65;
}
document.addEventListener('DOMContentLoaded', function() {
    @if(!auth()->user()->is_admin)
        // 阻止原生select的鼠标和键盘交互
        const selectEl = document.getElementById('assigned_staffs');
        selectEl.addEventListener('mousedown', e => e.preventDefault());
        selectEl.addEventListener('keydown', e => e.preventDefault());

        // 配置select2为只读模式(隐藏搜索框、禁用下拉)
        $('#assigned_staffs').select2({
            allowClear: false,
            minimumResultsForSearch: Infinity,
            dropdownCssClass: 'non-admin-select2-disabled'
        });
    @endif
});

方案二:替换为只读文本+隐藏原select(更直观)

如果不需要保留select的外观,直接展示选中的内容,同时隐藏原select来保留提交数据:

修改Blade代码:

<div class="form-group">
    <label for="assigned_staffs">{{ trans('cruds.appointment.fields.assigned_staff') }}</label>
    @if(auth()->user()->is_admin)
    <div style="padding-bottom: 4px">
        <span class="btn btn-info btn-xs select-all" style="border-radius: 0">{{ trans('global.select_all') }}</span>
        <span class="btn btn-info btn-xs deselect-all" style="border-radius: 0">{{ trans('global.deselect_all') }}</span>
    </div>
    <!-- 管理员可见的select -->
    <select class="form-control select2 {{ $errors->has('assigned_staffs') ? 'is-invalid' : '' }}" name="assigned_staffs[]" id="assigned_staffs" multiple>
        @foreach($assigned_staffs as $id => $assigned_staff)
            <option value="{{ $id }}" {{ (in_array($id, old('assigned_staffs', [])) || $appointment->assigned_staffs->contains($id)) ? 'selected' : '' }}>{{ $assigned_staff }}</option>
        @endforeach
    </select>
    @else
        <!-- 非管理员可见的只读文本 -->
        <div class="form-control-plaintext bg-light p-2">
            @php
                $selected = $appointment->assigned_staffs->pluck('name')->implode(', ');
            @endphp
            {{ $selected ?: trans('global.no_selected') }}
        </div>
        <!-- 隐藏的select,用于提交数据 -->
        <select name="assigned_staffs[]" id="assigned_staffs" multiple hidden>
            @foreach($assigned_staffs as $id => $assigned_staff)
                <option value="{{ $id }}" {{ (in_array($id, old('assigned_staffs', [])) || $appointment->assigned_staffs->contains($id)) ? 'selected' : '' }}>{{ $assigned_staff }}</option>
            @endforeach
        </select>
    @endif
    @if($errors->has('assigned_staffs'))
        <div class="invalid-feedback">
            {{ $errors->first('assigned_staffs') }}
        </div>
    @endif
    <span class="help-block">{{ trans('cruds.appointment.fields.assigned_staff_helper') }}</span>
</div>

方案对比:

  • 方案一保留了select的视觉样式,用户能看到所有选项但无法修改,适合需要展示完整选项列表的场景。
  • 方案二更简洁直观,用户直接看到选中结果,适合只需要展示已选内容的场景。

内容的提问来源于stack exchange,提问作者Arslan Malik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 22:24:59