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

类别选择异常:选父/子类自动全选,需改为单选

问题描述

系统包含类别、父类别及子类别层级结构。当前使用多选下拉框选择类别时,选择父类别或子类别会自动选中所有关联类别并全部保存至同一选项框中,需修改为仅能选择单个类别,而非全选关联类别。

现有代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 18:03:10