类别选择异常:选父/子类自动全选,需改为单选
问题描述
系统包含类别、父类别及子类别层级结构。当前使用多选下拉框选择类别时,选择父类别或子类别会自动选中所有关联类别并全部保存至同一选项框中,需修改为仅能选择单个类别,而非全选关联类别。
现有代码
Blade 视图代码
<div class="form-group col-md-3"> <label>@lang('Categories')</label> <select class="select2-multi-select form-control" name="categories[]" id="categories" multiple required"> @foreach ($categories as $category) <option value="{{ $category->id }}">@lang($category->name)</option> @php $prefix = '--'; @endphp @foreach ($category->allSubcategories as $subcategory) <option value="{{ $subcategory->id }}"> {{ $prefix }}@lang($subcategory->name) </option> @include('admin.partials.subcategories', [ 'subcategory' => $subcategory, 'prefix' => $prefix, ]) @endforeach @endforeach </select> </div> <script> 'use strict'; (function($){ var dropdownParent = $('.has-select2'); $('select[name="category_id"]').on('change', function () { var subcategories = $(this).find(':selected').data('subcats'); var output= `<div class="col-md-2"> <label class="font-weight-bold">Subcategory</label> </div> <div class="col-md-10"> <select class="form-control select2-basic" name="sub_category_id"> <option value="" selected disabled>@lang('Select One')</option> </div> `; if (subcategories.length != 0) { $.each(subcategories, function (key, val) { output += `<option value="${val.id}">${val.name}</option>`; }); output += `</select>` $('#sub-categories-div').html(output); } }); @if (request()-> routeIs('admin.products.edit')) var categories = []; @if($product->categories) categories = @json($product->categories->pluck('id')); @endif $('#categories').val(categories); $('.select2-multi-select').select2({ dropdownParent: dropdownParent, closeOnSelect: false }); @endif })(jQuery) </script>
Category 模型代码
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; class Category extends Model { use SoftDeletes; protected $guarded = ['id']; public function subcategories() { return $this->hasMany(Category::class, 'parent_id')->orderBy('name'); } public function allSubcategories() { return $this->subcategories()->with('allSubcategories'); } public function products() { return $this->belongsToMany(Product::class, 'products_categories', 'category_id', 'product_id'); } }
Controller 编辑方法代码
public function editProduct($id) { $data['product'] = Product::whereId($id)->first(); $data['categories'] = Category::with('allSubcategories')->where('parent_id', null)->get(); $data['pageTitle'] = "Edit Product"; return $data; }
修改方案
1. 前端 Blade 视图修改
将多选下拉框改为单选,调整 Select2 配置:
<div class="form-group col-md-3"> <label>@lang('Categories')</label> <!-- 移除 multiple 属性,修改 name 为 category_id,更换类名为单选的 select2-basic --> <select class="select2-basic form-control" name="category_id" id="categories" required> @foreach ($categories as $category) <option value="{{ $category->id }}">@lang($category->name)</option> @php $prefix = '--'; @endphp @foreach ($category->allSubcategories as $subcategory) <option value="{{ $subcategory->id }}"> {{ $prefix }}@lang($subcategory->name) </option> @include('admin.partials.subcategories', [ 'subcategory' => $subcategory, 'prefix' => $prefix, ]) @endforeach @endforeach </select> </div> <script> 'use strict'; (function($){ var dropdownParent = $('.has-select2'); $('select[name="category_id"]').on('change', function () { var subcategories = $(this).find(':selected').data('subcats'); var output= `<div class="col-md-2"> <label class="font-weight-bold">Subcategory</label> </div> <div class="col-md-10"> <select class="form-control select2-basic" name="sub_category_id"> <option value="" selected disabled>@lang('Select One')</option> </div> `; if (subcategories.length != 0) { $.each(subcategories, function (key, val) { output += `<option value="${val.id}">${val.name}</option>`; }); output += `</select>` $('#sub-categories-div').html(output); } }); @if (request()-> routeIs('admin.products.edit')) var categoryId = null; @if($product->categories->isNotEmpty()) // 只取第一个关联的类别ID(适配单选场景) categoryId = @json($product->categories->first()->id); @endif $('#categories').val(categoryId); // 初始化单选Select2,移除多选专属的closeOnSelect配置 $('.select2-basic').select2({ dropdownParent: dropdownParent }); @endif })(jQuery) </script>
2. 后端保存/更新逻辑修改
在处理产品保存或更新的控制器方法中,将多类别同步改为单个类别关联:
// 原多选逻辑 // $product->categories()->sync($request->categories); // 修改为单选逻辑 $product->categories()->sync([$request->category_id]);
3. 修改说明
- 移除
multiple属性后,下拉框默认仅支持单个选项选择,不会自动选中关联类别 - 移除
closeOnSelect: false配置,单选场景下选择选项后自动关闭下拉框,符合常规交互 - 编辑页面赋值时取产品关联的第一个类别ID,适配单选需求
内容的提问来源于stack exchange,提问作者Abdelrahman Wagih
相关产品推荐
相关产品推荐

