Laravel Blade中使用select2-multiple类出现选项重复问题
问题描述
使用Laravel框架,通过Blade模板实现下拉框预选中项时,出现两个问题:
- 预选中的选项重复显示,同一个选项被渲染多次;
- 给下拉框添加
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 })
问题原因
- 重复选项输出:原Blade模板循环逻辑冗余,多次遍历整个
$tags[$tagId]数组,易导致同一个option被重复输出;若$tags[$tagId]集合本身包含重复ID的记录,也会直接生成重复的选中option,Select2会为每个选中的option渲染一个span标签,最终出现重复。 - 重复初始化风险:若页面多次执行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
相关产品推荐
相关产品推荐

