如何在Laravel Voyager v1.6.0的多选框中添加‘全选’功能
问题描述
我刚开始学习Laravel和Voyager,我的users表与department表存在多对多(belongs to many)关系。创建用户时,系统提供多选下拉框保存用户所属部门,Voyager通过默认表单字段自动处理新增和编辑操作。我想在用户创建表单的多选框中添加“全选”按钮,但遇到了问题,请问该如何实现?
用户创建表单代码
<label for="department">{{ __('Department') }}</label> @php $row = $dataTypeRows->where('field', 'user_belongsto_department_relationship')->first(); $options = $row->details; @endphp @include('voyager::formfields.relationship') </div>
Voyager中处理多选框的表单字段代码
@elseif($options->type == 'belongsToMany') @if (isset($view) && ($view == 'browse' || $view == 'read')) @php $relationshipData = isset($data) ? $data : $dataTypeContent; $selected_values = isset($relationshipData) ? $relationshipData ->belongsToMany($options->model, $options->pivot_table, $options->foreign_pivot_key ?? null, $options->related_pivot_key ?? null, $options->parent_key ?? null, $options->key) ->get() ->map(function ($item, $key) use ($options) { return $item->{$options->label}; }) ->all() : []; @endphp @if ($view == 'browse') @php $string_values = implode(', ', $selected_values); if (mb_strlen($string_values) > 25) { $string_values = mb_substr($string_values, 0, 25) . '...'; } @endphp @if (empty($selected_values)) <p>{{ __('voyager::generic.no_results') }}</p> @else <p>{{ $string_values }}</p> @endif @else @if (empty($selected_values)) <p>{{ __('voyager::generic.no_results') }}</p> @else <ul> @foreach ($selected_values as $selected_value) <li>{{ $selected_value }}</li> @endforeach </ul> @endif @endif @else <select id={{ $relationshipField }} class="form-control select2-ajax @if (isset($options->taggable) && $options->taggable === 'on') taggable @endif" name="{{ $relationshipField }}[]" multiple data-get-items-route="{{ route('voyager.' . $dataType->slug . '.relation') }}" data-get-items-field="{{ $row->field }}" @if (!is_null($dataTypeContent->getKey())) data-id="{{ $dataTypeContent->getKey() }}" @endif data-method="{{ !is_null($dataTypeContent->getKey()) ? 'edit' : 'add' }}" @if (isset($options->taggable) && $options->taggable === 'on') data-route="{{ route('voyager.' . \Illuminate\Support\Str::slug($options->table) . '.store') }}" data-label="{{ $options->label }}" data-error-message="{{ __('voyager::bread.error_tagging') }}" @endif @if ($row->required == 1) required @endif> @php $selected_keys = []; if (!is_null($dataTypeContent->getKey())) { $selected_keys = $dataTypeContent->belongsToMany($options->model, $options->pivot_table, $options->foreign_pivot_key ?? null, $options->related_pivot_key ?? null, $options->parent_key ?? null, $options->key)->pluck($options->table . '.' . $options->key); } $selected_keys = old($relationshipField, $selected_keys); $selected_values = app($options->model) ->whereIn($options->key, $selected_keys) ->pluck($options->label, $options->key); @endphp @if (!$row->required) <option value="">{{ __('voyager::generic.none') }}</option> @endif @foreach ($selected_values as $key => $value) <option value="{{ $key }}" selected="selected">"{{ $value }}"</option> @endforeach </select> @endif @endif
解决方案
Voyager的多选下拉框基于Select2插件实现,无需修改后端逻辑,仅通过前端添加按钮和JS逻辑即可实现全选功能,步骤如下:
1. 在表单中添加全选/取消全选按钮
将按钮插入到下拉框的上方,修改后的用户创建表单代码如下:
<label for="department">{{ __('Department') }}</label> <!-- 新增全选按钮组 --> <button type="button" class="btn btn-sm btn-secondary mb-2" id="select-all-departments">全选部门</button> <button type="button" class="btn btn-sm btn-light mb-2" id="deselect-all-departments">取消全选</button> @php $row = $dataTypeRows->where('field', 'user_belongsto_department_relationship')->first(); $options = $row->details; @endphp @include('voyager::formfields.relationship') </div>
2. 编写Select2全选逻辑的JavaScript
Voyager页面默认已加载jQuery和Select2,直接添加以下脚本(可放在页面底部或自定义JS文件中):
$(document).ready(function() { // 监听Select2展开事件,确保AJAX选项加载完成后绑定按钮事件 $(document).on('select2:open', '#user_belongsto_department_relationship', function() { // 全选逻辑 $('#select-all-departments').off('click').on('click', function() { const selectElement = $('#user_belongsto_department_relationship'); const allOptionIds = []; // 获取所有未选中的选项ID $('.select2-results__option[role="option"]').each(function() { const optionId = $(this).data('id'); if (optionId && !$(this).hasClass('select2-results__option--selected')) { allOptionIds.push(optionId); } }); // 设置所有选项为选中状态并触发变更 selectElement.val(allOptionIds).trigger('change'); }); // 取消全选逻辑 $('#deselect-all-departments').off('click').on('click', function() { const selectElement = $('#user_belongsto_department_relationship'); selectElement.val([]).trigger('change'); }); }); });
3. 注意事项
- 确认下拉框ID正确:代码中使用的
user_belongsto_department_relationship对应关系字段的ID,需与页面实际渲染的select元素ID一致。 - 因下拉选项是AJAX加载,必须监听
select2:open事件,确保选项加载完成后再执行全选逻辑。 - 编辑页面同样适用该逻辑,点击全选会保留已选中的选项,追加所有未选中项。
内容的提问来源于stack exchange,提问作者Naushad Punjani
相关产品推荐
相关产品推荐

