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
相关产品推荐
相关产品推荐

