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

Laravel Backpack子字段多表单中include_all_form_fields关联查询实现

问题场景

Laravel Backpack表单中存在1-N关联的重复子字段(示例中的anyRows),每个子表单包含status(下拉选择)和service_id(select2_from_ajax类型)字段。需求是让每个子行的service_id下拉选项仅依据当前行的status值过滤,而非所有行的status,同时希望将anyRows数组的行号传递到后端fetchService方法中。

现有表单配置代码:

public function setupCreateOperation()
{
    ...
    $this->crud->addFields([
        [
            'name'     => 'anyRows',
            'type'     => 'relationship',
            'label'    => 'Table 1-N',
            'subfields' => [
                [
                    'name'    => 'status',
                    'label'   => trans($this->trans_prefix . 'status'),
                    'type'    => 'select_from_array',
                    'options' => [
                        0 => 'one',
                        1 => 'two'
                    ],
                ],
                [
                    'name'                    => 'service_id',
                    'label'                   => trans($this->trans_prefix . 'service'),
                    'type'                    => 'select2_from_ajax',
                    'entity'                  => 'service',
                    'method'                  => 'post',
                    'data_source'             => url('fetch/service'),
                    'minimum_input_length'    => 0,
                    'include_all_form_fields' => true
                ]
            ]
        ]
    ]);
}

当前后端fetchService接收的请求数据格式:

array:2 [ 
    "q" => ""
    "form" => array:4 [
        0 => array:2 [
          "name" => "anyRows[0][status]"
          "value" => "1"
        ]
        1 => array:2 [
          "name" => "anyRows[0][service]"
          "value" => null // 该下拉选项需依赖anyRows[0][status]
        ]
        2 => array:2 [
          "name" => "anyRows[1][status]"
          "value" => "0"
        ]
        3 => array:2 [
          "name" => "anyRows[1][service]"
          "value" => null // 该下拉选项需依赖anyRows[1][status]
        ]
    ]
]
解决方案

步骤1:修改字段配置,传递子行索引

在service_id字段配置中添加ajax_extra_data,通过JS获取当前子行的索引并作为参数传递到后端:

[
    'name'                    => 'service_id',
    'label'                   => trans($this->trans_prefix . 'service'),
    'type'                    => 'select2_from_ajax',
    'entity'                  => 'service',
    'method'                  => 'post',
    'data_source'             => url('fetch/service'),
    'minimum_input_length'    => 0,
    'include_all_form_fields' => true,
    // 新增:传递当前行索引
    'ajax_extra_data' => <<<JS
        function() {
            var rowIndex = $(this).closest('.repeatable-row').index();
            return {
                row_index: rowIndex
            };
        }
JS
]

步骤2:后端解析行号并过滤数据

在fetchService方法中,通过row_index定位对应行的status值,再用该值过滤Service数据:

use Illuminate\Http\Request;

public function fetchService(Request $request)
{
    $rowIndex = $request->input('row_index');
    
    // 从表单数据中匹配对应行的status
    $status = collect($request->input('form'))
        ->firstWhere('name', "anyRows[$rowIndex][status]")['value'] ?? null;

    if (is_null($status)) {
        return response()->json([]);
    }

    // 根据status和搜索关键词过滤服务数据
    $services = \App\Models\Service::where('status', $status)
        ->where('name', 'like', '%' . $request->input('q') . '%')
        ->select('id', 'name')
        ->get();

    return response()->json($services);
}

步骤3:监听status变化,自动刷新下拉选项(可选)

若需要在status值改变时自动更新对应行的service_id选项,添加以下JS代码(可放在页面脚本或自定义JS文件中):

$(document).on('change', '.repeatable-row select[name*="status"]', function() {
    const $serviceSelect = $(this).closest('.repeatable-row').find('select[name*="service_id"]');
    $serviceSelect.val(null).trigger('change');
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 15:42:03