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
相关产品推荐
相关产品推荐

