Drupal自定义模块中自定义Twig模板无法渲染表单的问题
我之前在做Drupal表单自定义的时候也踩过这个模板关联的坑,你的问题核心是混淆了表单级主题和页面级html主题的用法,下面分情况给你梳理解决方案:
一、先明确你的需求
首先要搞清楚:你是想让包含该表单的整个页面使用自定义的html模板,还是只想自定义表单本身的渲染结构?这两种场景的实现方式完全不同。
场景1:让表单所在页面使用自定义html模板
如果你要替换整个页面的html.html.twig,那不能通过表单的#theme来设置,因为html.html.twig是页面顶级模板,由页面渲染流程控制,不是表单的主题。你需要通过添加页面模板建议来实现:
在
resume.module中添加模板建议
实现hook_preprocess_html()来判断当前页面是否是你的表单页面,然后注入自定义模板建议:function resume_preprocess_html(&$variables) { // 获取当前路由名称,替换成你的表单对应的路由(比如你在routing.yml里定义的路由) $current_route = \Drupal::routeMatch()->getRouteName(); if ($current_route === 'resume.my_form_route') { // 添加自定义html模板建议 $variables['theme_hook_suggestions'][] = 'html__resume__myform'; } }在自定义html模板中渲染表单
你的html--resume--myform.html.twig里,表单是包含在页面的content区域中的,所以用以下代码渲染(可以复制原html.html.twig的结构,替换需要自定义的部分):<!DOCTYPE html> <html{{ html_attributes }}> <head> {{ head }} <title>{{ head_title|safe_join(' | ') }}</title> {{ styles }} {{ scripts }} </head> <body{{ attributes }}> {{ page_top }} {{ page }} {# 这里的page.content就包含你的表单 #} {{ page_bottom }} </body> </html>
场景2:自定义表单本身的渲染模板(不替换整个html页面)
如果你只是想自定义表单的结构,不需要替换整个页面的html模板,那你之前的主题注册和#theme设置有误:
修改表单类中的
#theme设置
把表单的主题钩子改成表单级的,而不是html级的:public function buildForm(array $form, FormStateInterface $form_state) { // 设置表单自身的主题钩子 $form['#theme'] = 'resume_myform'; $form['candidate_name'] = [ '#type' => 'textfield', '#title' => t('Candidate Name:'), '#required' => TRUE, ]; $form['actions']['#type'] = 'actions'; $form['actions']['submit'] = [ '#type' => 'submit', '#value' => $this->t('Save2'), '#button_type' => 'primary', ]; return $form; // 注意这里要加分号,你之前的代码漏了 }正确注册表单主题
在resume.module中注册表单主题,注意模板文件名的下划线/连字符转换:function resume_theme() { return [ 'resume_myform' => [ 'render element' => 'form', 'template' => 'resume-myform', // 对应templates/resume-myform.html.twig ], ]; }编写表单模板
在templates/resume-myform.html.twig中,你可以直接渲染整个表单,或者逐个控制元素:<div class="custom-resume-form"> <h3>{{ 'Candidate Info'|t }}</h3> {{ form.candidate_name }} <div class="form-actions"> {{ form.actions.submit }} </div> {# 别忘了渲染表单的隐藏元素 #} {{ form.form_build_id }} {{ form.form_token }} {{ form.form_id }} </div>
二、必做的缓存清理和检查
不管哪种场景,做完修改后一定要:
- 清除Drupal的所有缓存(配置 -> 性能 -> 清除所有缓存)
- 确认模板文件放在模块的
templates目录下,文件名大小写、连字符/下划线完全匹配 - 检查模板文件的权限,确保Web服务器可以读取它
内容的提问来源于stack exchange,提问作者user3646821

