无需JQuery通过Ajax提交表单实现Symfony联动下拉字段更新
可行解决方案
方案1:前端兼容现有逻辑,无需修改后端代码
你之前手动构造FormData在编辑场景失效的核心原因是编辑模式下表单包含的隐藏主键字段、其他必填隐藏参数没有被提交,Symfony表单组件无法识别是编辑操作,只需要在构造FormData时补充所有隐藏字段即可兼容新增和编辑场景:
blockchain.addEventListener('change', function () { const form = this.closest('form'); const method = form.method; const url = form.action; const formdata = new FormData(); // 添加当前公链字段值 formdata.append(this.name, this.value); // 添加CSRF校验参数 formdata.append(csrf.name, csrf.value); // 批量添加所有隐藏字段,兼容编辑场景的主键等参数 form.querySelectorAll('input[type="hidden"]').forEach(hiddenInput => { formdata.append(hiddenInput.name, hiddenInput.value); }); const request = new XMLHttpRequest(); request.open(method, url, true); request.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); request.onload = function () { if (this.status >= 200 && this.status < 400) { const html = new DOMParser().parseFromString(this.response, 'text/html'); dapp.innerHTML = html.querySelector('#strategy_farming_dapp').innerHTML; } else { console.log('Server error'); } }; request.onerror = function () { console.log('Connection error'); }; request.send(formdata); });
方案2:后端新增独立联动接口,性能更优
如果不想复用原有表单接口,可以单独新增公链对应Dapp选项的查询接口,完全脱离原有表单逻辑,请求更轻量:
- Symfony后端新增接口示例:
// 控制器中新增路由 #[Route('/api/dapp-options/{blockchainId}', name: 'api_dapp_options')] public function getDappOptions(int $blockchainId, DappRepository $dappRepository): JsonResponse { $dapps = $dappRepository->findBy(['blockchain' => $blockchainId]); $options = []; foreach ($dapps as $dapp) { $options[] = [ 'id' => $dapp->getId(), 'name' => $dapp->getName() ]; } return $this->json($options); }
- 前端联动代码简化为:
blockchain.addEventListener('change', async function () { const blockchainId = this.value; if (!blockchainId) { dapp.innerHTML = '<option value="">请先选择公链</option>'; return; } try { const res = await fetch(`/api/dapp-options/${blockchainId}`); const dapps = await res.json(); // 清空原有选项 dapp.innerHTML = ''; // 添加默认空选项 const emptyOption = document.createElement('option'); emptyOption.value = ''; emptyOption.textContent = '请选择Dapp'; dapp.appendChild(emptyOption); // 渲染新选项 dapps.forEach(dappItem => { const option = document.createElement('option'); option.value = dappItem.id; option.textContent = dappItem.name; dapp.appendChild(option); }); } catch (e) { console.log('获取Dapp列表失败', e); } });
补充说明之前方案3失效的原因:提交JSON格式数据时需要额外设置Content-Type: application/json请求头,且Symfony侧需要通过$request->toArray()而非$request->request获取解析后的JSON参数,你之前的写法缺少请求头且取值方式不对,因此无法拿到数据。
内容的提问来源于stack exchange,提问作者0xPunt
相关产品推荐
相关产品推荐

