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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 12:32:04