【问题标题】:Symfony2 custom form renderer helper functionSymfony2 自定义表单渲染器辅助函数
【发布时间】:2016-04-18 12:35:49
【问题描述】:

我想定义一个新的 twig 函数“form_field”,它呈现 form_labelform_widgetform_errors。 我不想覆盖form_row,因为我已经出于不同的目的这样做了:form_row 还包装了我的布局所需的<div/> 容器。具体来说,我添加了引导类。

我为什么需要这个?通常我使用form_row,但我有很多表单行,我想在同一行中放置两个或更多字段(例如“名字”和“姓氏”)。在这些情况下,我会手动定义包装 <div/>,但我不想每次都编写三个函数调用(form_labelform_widgetform_errors)。

我试图指定一个自定义函数,但在那里调用 twig 函数时出现异常。对于这个解决方案,我需要知道如何从自定义函数调用 Twig 函数。

我的第二次尝试是让 Symfony 的解决方案适应它自己的表单助手。我在 vendor/symfony/symfony/src/Symfony/Bridge/Twig/Extension/FormExtension.php 中找到了这一行:

new \Twig_SimpleFunction('form_widget', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))),

看起来像一个实际上只是渲染一个块的函数。当我在我的 AppBundle 中调整该行时,引发了一个异常,其中 Symfony 声称名为“form_field”的块未定义。但是,我在自定义表单模板中定义了这个块:

{% use 'bootstrap_3_horizontal_layout.html.twig' %}

{%- block form_field -%}
    {{- form_label(form) -}}
    {{- form_widget(form) -}}
    {{- form_errors(form) -}}
{%- endblock form_field -%}

【问题讨论】:

  • 由于 Symfony 的表单主题有一些神奇的改进,解决方案可能取决于您的表单是如何构建的。名字和姓氏字段是否作为单一的复合类型字段添加到表单构建器中?
  • 这是两个单独的字段。我会这样添加它们:<div ...>form_field(form.firstName)</div><div ...>form_field(form.lastName)</div>

标签: php forms symfony twig customization


【解决方案1】:

声明一个twig模板Form/form_field.html.twig:

{%- block form_field -%}
    {{- form_label(form, label) -}}
    {{- form_widget(form) -}}
    {{- form_errors(form) -}}
{%- endblock form_field -%}

然后我在我的 Twig 自定义函数中使用了renderBlock 方法。这是我的树枝扩展文件,如here所述:

namespace AppBundle\Twig;

class AppExtension extends \Twig_Extension
{
    protected $environment;
    private $template;

    public function __construct(\Twig_Environment $env)
    {
        $this->environment = $env;
    }


    public function getFunctions()
    {
        return array(
            'form_field' => new \Twig_SimpleFunction('form_field', array($this, 'formField'), array(
                'is_safe' => array('html')
            ))
        );
    }

    public function formField($form, $label = null)
    {
        $this->template = $this->environment->loadTemplate( '::Form/form_field.html.twig' );

        return $this->template->renderBlock('form_field', array(
            'form' => $form,
            'label' => $label
        ));
    }

    /**
     * Returns the name of the extension.
     *
     * @return string The extension name
     */
    public function getName()
    {
        return 'app_extension';
    }
}

我将 DI 容器配置为为 AppExtension 服务传递 Twig_Environment:

services:
    app.twig_extension:
        class: AppBundle\Twig\AppExtension
        arguments:
            - '@twig'
        tags:
            - { name: twig.extension }

【讨论】:

  • 感谢您的回答,它对我有帮助,官方文档对这个话题相当了解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-17
相关资源
最近更新 更多