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

[PHP][Laravel][AJAX] 基于Select2和AJAX的级联下拉菜单无法正常工作

问题描述

尝试使用Select2创建依赖级联下拉菜单,选择父级「服务组(group service)」时,子级「服务(service)」选项无法显示,相关代码如下:


1. 路由代码

Route::controller(TaskController::class)->prefix('dashboard/task')->middleware(['role:admin|operator|user-bisnis|user-qa'])->group(function () {
    Route::get('/', 'index');
    Route::get('/create', 'create')->name('task.create');
    Route::post('/', 'store')->name('task.store');
    Route::get('/edit/{id}', 'edit')->name('task.edit');
    Route::post('/update/{id}', 'update')->name('task.update');
    Route::post('/delete/{id}', 'destroy')->name('task.delete');
    Route::get('/groupservice', 'getGroupService')->name('groupservice.select');
    Route::get('/service', 'getService')->name('service.select');
});

2. 控制器代码

public function getService(Request $request)
{
    $service = [];
    $groupserviceID = $request->groupserviceID;
    if ($request->has('q')) {
        $search = $request->q;
        $service = Service::select("id", "nama")
            ->where('gruplayanan_id', $groupserviceID)
            ->Where('deskripsi', 'LIKE', "%$search%")
            ->get();
    } else {
        $service = Service::where('gruplayanan_id', $groupserviceID)->limit(10)->get();
    }
    return response()->json($service);
}

3. 视图代码

JavaScript 部分

$(document).ready(function() {

  $('#gruplayanan_id').change(function() {
    //clear select
    $("#layanan_id").empty();
    //set id
    let groupserviceID = $(this).val();
    if (groupserviceID) {
        $('#layanan_id').select2({
          allowClear: true,
          ajax: {
              url: "{{ route('service.select') }}?groupserviceID=" + groupserviceID,
              dataType: 'json',
              delay: 250,
              processResults: function(data) {
                return {
                    results: $.map(data, function(item) {
                      return {
                          text: item.nama,
                          id: item.id
                      }
                    })
                };
              }
          }
        });
    }
  });

$('#gruplayanan_id').on('select2:clear', function(e) {
  $("#layanan_id").select2();
});
});

HTML 部分

<head>
{{-- Select2 --}}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.8/js/select2.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.8/css/select2.min.css">
  
</head>

<body>
      <div class="mb-3">
        <label for="gruplayanan" class="form-label">Pilih Group Layanan</label><span style="color: red;">*</span>
          <select class="theSelect" name="gruplayanan_id" id="gruplayanan_id" style="width: 300px" autofocus required>
            <option hidden></option>
              @foreach ($groupservice as $item => $groupservice)
                <option value="{{ $groupservice->id }}">{{ $groupservice->deskripsi }}</option>
              @endforeach
          </select>
      </div>
      <div class="mb-3">
        <label for="layanan" class="form-label">Pilih Layanan</label><span style="color: red;">*</span>
          <select class="theSelect" name="layanan_id" id="layanan_id" style="width: 300px" autofocus required>
          </select>
      </div>
</body>

问题排查与解决办法

1. 修复重复初始化Select2的问题

每次父级下拉框变化时重新初始化子级Select2会导致组件状态混乱,应改为仅初始化一次,动态更新请求参数:

$(document).ready(function() {
    // 初始化父级Select2
    $('#gruplayanan_id').select2({
        allowClear: true,
        placeholder: "Pilih Group Layanan"
    });

    // 初始化子级Select2,配置动态AJAX参数
    $('#layanan_id').select2({
        allowClear: true,
        placeholder: "Pilih Layanan",
        ajax: {
            url: "{{ route('service.select') }}",
            dataType: 'json',
            delay: 250,
            data: function(params) {
                return {
                    q: params.term,
                    groupserviceID: $('#gruplayanan_id').val()
                };
            },
            processResults: function(data) {
                return {
                    results: $.map(data, function(item) {
                        return {
                            text: item.nama,
                            id: item.id
                        }
                    })
                };
            }
        },
        disabled: true // 初始禁用,选择父级后启用
    });

    // 父级选择变化时更新子级状态
    $('#gruplayanan_id').on('change', function() {
        let groupserviceID = $(this).val();
        let $layanan = $('#layanan_id');
        
        if (groupserviceID) {
            $layanan.prop('disabled', false);
            $layanan.val(null).trigger('change'); // 清空并触发重新加载
        } else {
            $layanan.prop('disabled', true);
            $layanan.val(null).trigger('change');
        }
    });

    // 父级清空时同步处理子级
    $('#gruplayanan_id').on('select2:clear', function() {
        $('#layanan_id').val(null).prop('disabled', true).trigger('change');
    });
});

2. 控制器参数验证与代码规范优化

添加参数验证避免SQL错误,同时统一代码风格:

public function getService(Request $request)
{
    // 强制验证父级ID参数
    $request->validate([
        'groupserviceID' => 'required|integer',
    ]);

    $groupserviceID = $request->groupserviceID;
    $query = Service::select("id", "nama")->where('gruplayanan_id', $groupserviceID);

    // 处理搜索关键词
    if ($request->has('q')) {
        $search = $request->q;
        $query->where('deskripsi', 'LIKE', "%{$search}%");
    }

    $service = $query->limit(10)->get();
    return response()->json($service);
}

3. 检查AJAX请求状态

打开浏览器开发者工具(F12)→ Network标签,选择父级服务组后:

  • 确认请求URL是否携带正确的groupserviceID参数
  • 查看响应是否返回合法的JSON数据
  • 检查是否存在404/500等错误状态码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 05:25:16