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

Laravel Blade中使用select2-multiple类出现选项重复问题

问题描述

使用Laravel框架,通过Blade模板实现下拉框预选中项时,出现两个问题:

  1. 预选中的选项重复显示,同一个选项被渲染多次;
  2. 给下拉框添加select2-multiple类启用Select2多选后,选项能正确选中,但选中区域生成了重复的span标签(表现为同一个选中选项对应两个span元素)。
原代码

Blade模板代码

<div class="tagging-wrapper">
    <select class="product-edit-tagging form-control select2-multiple " style="width: 100%;"
            name="tag_{{ $tagId }}[]"
            {{ $tag->is_unique ? ' ' : 'multiple' }}
            placeholder="{{ $tag->name . ($tag->is_mandatory ? ' *' : '') }}"
            @if($tag->is_mandatory) data-mandatory="{{ $tag->name }}" @endif
            id="tag_{{$tagId}}" data-tagging="{{$tagId}}">
        @if(!empty($tags[$tagId]))
            @if(config('modules.site.headline_activated'))
                @foreach ($tags[$tagId] as $child)
                    @if($child->is_headline)
                            <?php $showHeadline = 0; ?>
                            @foreach($tags[$tagId] as $headlineChild)
                                @if($headlineChild->headline_id == $child->id)
                                    <?php $showHeadline = 1; ?>
                                    @break
                                @endif
                            @endforeach
                            @if($showHeadline == 1)
                                <optgroup label="{{ $child->name }}">
                                    @foreach($tags[$tagId] as $headlineChild)
                                        @if($headlineChild->headline_id == $child->id)
                                            <option test1="test1" value="{{ $headlineChild->id }}"{{ in_array($headlineChild->id, $productTagIds) ? ' selected="selected"' : '' }} data-additional-info="{{$headlineChild->id}}">{{ $headlineChild->name }}</option>
                                        @endif
                                    @endforeach
                                </optgroup>
                            @endif
                    @else
                        @if($child->headline_id == 0)
                        <option data-additional-info="test2" value="{{ $child->id }}"{{ in_array($child->id, $productTagIds) ? ' selected="selected"' : '' }}>
                            {{ $child->name }}
                        </option>
                        @endif
                    @endif
                @endforeach
            @else
                @foreach ($tags[$tagId] as $child)
                    <option value="{{ $child->id }}"{{ in_array($child->id, $productTagIds) ? ' selected="selected"' : '' }}>
                        {{ $child->name }}
                    </option>
                @endforeach
            @endif
        @endif
    </select>
</div>

JS初始化代码

$(".select2-multiple").select2({
    maximumSelectionLength: 5
})
问题原因
  1. 重复选项输出:原Blade模板循环逻辑冗余,多次遍历整个$tags[$tagId]数组,易导致同一个option被重复输出;若$tags[$tagId]集合本身包含重复ID的记录,也会直接生成重复的选中option,Select2会为每个选中的option渲染一个span标签,最终出现重复。
  2. 重复初始化风险:若页面多次执行Select2初始化代码,会导致组件重复渲染,生成额外DOM元素。
解决方案

1. 清理数据与优化Blade循环逻辑

先确保数据无重复,再重构循环逻辑,避免重复输出option:

步骤1:控制器层预处理数据(推荐)

在传递$tags到视图前,先对数据去重并分组,减少模板层逻辑复杂度:

// 假设$tags[$tagId]是Eloquent集合
$tags[$tagId] = $tags[$tagId]->unique('id'); // 按ID去重
$tags[$tagId] = $tags[$tagId]->groupBy(function ($item) {
    if ($item->is_headline) {
        return 'headlines';
    } elseif ($item->headline_id > 0) {
        return 'children_' . $item->headline_id;
    } else {
        return 'normal';
    }
});

步骤2:修改Blade模板代码

<div class="tagging-wrapper">
    <select class="product-edit-tagging form-control select2-multiple" style="width: 100%;"
            name="tag_{{ $tagId }}[]"
            {{ $tag->is_unique ? '' : 'multiple' }}
            placeholder="{{ $tag->name . ($tag->is_mandatory ? ' *' : '') }}"
            @if($tag->is_mandatory) data-mandatory="{{ $tag->name }}" @endif
            id="tag_{{$tagId}}" data-tagging="{{$tagId}}">
        @if(!empty($tags[$tagId]))
            @if(config('modules.site.headline_activated'))
                {{-- 处理分类标题及其子项 --}}
                @foreach($tags[$tagId]['headlines'] ?? [] as $headline)
                    @php
                        $childrenKey = 'children_' . $headline->id;
                        $children = $tags[$tagId][$childrenKey] ?? collect();
                    @endphp
                    @if($children->isNotEmpty())
                        <optgroup label="{{ $headline->name }}">
                            @foreach($children as $child)
                                <option value="{{ $child->id }}" {{ in_array($child->id, $productTagIds) ? 'selected="selected"' : '' }} data-additional-info="{{$child->id}}">
                                    {{ $child->name }}
                                </option>
                            @endforeach
                        </optgroup>
                    @endif
                @endforeach
                {{-- 处理无分类的普通选项 --}}
                @foreach($tags[$tagId]['normal'] ?? [] as $child)
                    <option value="{{ $child->id }}" {{ in_array($child->id, $productTagIds) ? 'selected="selected"' : '' }} data-additional-info="test2">
                        {{ $child->name }}
                    </option>
                @endforeach
            @else
                @foreach ($tags[$tagId] as $child)
                    <option value="{{ $child->id }}" {{ in_array($child->id, $productTagIds) ? 'selected="selected"' : '' }}>
                        {{ $child->name }}
                    </option>
                @endforeach
            @endif
        @endif
    </select>
</div>

2. 避免Select2重复初始化

修改JS代码,初始化前先销毁已存在的Select2实例,防止重复渲染:

$(".select2-multiple").each(function() {
    // 检查是否已初始化Select2,若已初始化则销毁
    if ($(this).data('select2')) {
        $(this).select2('destroy');
    }
}).select2({
    maximumSelectionLength: 5
});
验证效果

完成上述修改后:

  • 下拉框不会再输出重复的option标签;
  • Select2选中区域只会为每个选中项生成一个span标签,重复问题解决。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 06:54:59