Drupal 9:通过AJAX加载的表单无法正常提交问题求助
解决Drupal表单AJAX动态加载后无法提交的问题
问题根源
直接通过jQuery AJAX获取并插入表单HTML时,Drupal表单的action属性生成的是临时表单路由令牌,且表单所需的Drupal JS行为未被正确绑定,导致提交失败。而直接访问Controller B时,Drupal完整请求流程会处理表单的路由、令牌和行为绑定,因此能正常提交。
最优解决方案:改用Drupal原生AJAX框架
Drupal自带的AJAX系统会自动处理表单的路由生成、行为绑定和提交逻辑,是最可靠的解决方式:
1. 修改Controller B的响应类型
将返回JSON改为返回Drupal的AJAX响应,让系统处理表单插入:
use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\ReplaceCommand; public function get_form() { $form = \Drupal::formBuilder()->getForm('Drupal\my_module\Form\MyForm'); $response = new AjaxResponse(); // 用表单内容替换#form容器 $response->addCommand(new ReplaceCommand('#form', $form)); return $response; }
2. 调整前端实现(两种可选方式)
方式一:使用Drupal.ajax API替代纯jQuery AJAX
$('#ajax-link').on('click', function(e) { e.preventDefault(); // 初始化Drupal AJAX对象 const ajax = Drupal.ajax({ url: '/controller-B/get-form', wrapper: 'form', // 目标容器ID method: 'replace', progress: { type: 'throbber' } // 加载动画 }); ajax.execute(); });
方式二:使用Drupal内置AJAX链接(无需自定义JS)
直接在Controller A的输出中使用带AJAX属性的链接:
<a id="ajax-link" href="/controller-B/get-form" class="use-ajax" data-use-ajax-wrapper="form">Click here to display the form</a> <div id="form"></div>
注:确保页面已加载core/drupal.ajax库(默认Drupal会加载,自定义页面需手动引入)。
备选方案:纯jQuery AJAX兼容处理
若必须保留纯jQuery AJAX实现,需补充两个关键步骤:
1. 手动设置表单action路径
在Controller B中明确指定表单提交路径,避免生成临时令牌路径:
public function get_form() { $form = \Drupal::formBuilder()->getForm('Drupal\my_module\Form\MyForm'); // 替换为你的表单提交路由 $form['#action'] = \Drupal\Core\Url::fromRoute('my_module.form_submit')->toString(); $output = \Drupal::service('renderer')->render($form); $data = new \StdClass(); $data->output = $output; return new JsonResponse($data); }
2. 插入表单后绑定Drupal行为
在JS的success回调中调用Drupal.attachBehaviors(),触发表单JS行为绑定:
$("#ajax-link").on("click", function() { $.ajax({ url: "/controller-B/get-form", type: "POST", dataType: "JSON", success: function(data) { $("#form").html(data.output); // 绑定Drupal表单行为 Drupal.attachBehaviors("#form"); } });
关键说明
- 备选方案不推荐:手动处理action和行为绑定可能遗漏Drupal表单的安全验证(如CSRF令牌),长期维护性差。
- 确保表单类
MyForm正确实现getFormId()、buildForm()、submitForm()方法,且提交路由已在routing.yml中正确配置。
内容的提问来源于stack exchange,提问作者Hubert
相关产品推荐
相关产品推荐

