Symfony twig如何将类添加到表单行

Symfony twig如何将类添加到表单行,symfony,twig,symfony-forms,Symfony,Twig,Symfony Forms,我正在使用Twig在Symfony 2.3中构建一个项目。我想在表单行块中添加一个类。我使用的表单主题文件包含: {% block form_row %} <div class="form-row"> {{ form_label(form) }} {{ form_widget(form) }} {{ form_errors(form) }} </div> {% endblock %} (注意,我把错误类逻辑

我正在使用Twig在Symfony 2.3中构建一个项目。我想在表单行块中添加一个类。我使用的表单主题文件包含:

{% block form_row %}
    <div class="form-row">
        {{ form_label(form) }}
        {{ form_widget(form) }}
        {{ form_errors(form) }}
    </div>
{% endblock %}
(注意,我把
错误
类逻辑也放在那里,因为这需要保留)。 然后在表单生成器中:

$builder
        ->add('first_name', 'text', array(
            'attr' => array(
                'class' => 'form-row-split'
            )
        ));
这几乎可以工作,但它在任何地方都添加了这个类,并且还将小部件id添加到行中

<div id="myform_first_name" class="form-row form-row-split">
    <label for="myform_first_name">First name</label>
    <input id="myform_first_name" class="form-row-split" type="text" name="myform[first_name]">
</div>

名字
我可以想出一些可能的解决方案,但没有一个是漂亮的或直接的。肯定有一种简单的方法可以做到这一点吗?

说:您总是能够将attr传递给渲染元素:

{{ form_start(form, {'attr': {'class': 'your-class'}} ) }}
    {{ form_label(form, {'attr': {'class': 'your-class'}}) }}
    {{ form_widget(form, {'attr': {'class': 'your-class'}}) }}
    {{ form_errors(form, {'attr': {'class': 'your-class'}}) }}
{{ form_end(form) }}

实际上,这个问题有一个相当简单的解决方案。我只需要一个表单类型扩展来扩展基本表单类型,以允许一个额外的可用选项:

按照文档中的示例,我创建了一个新的表单类型扩展:

// src/Acme/FrontendBundle/Form/Extension/FormTypeExtension.php

namespace Acme\FrontendBundle\Form\Extension;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * Class FormTypeExtension
 * @package Acme\FrontendBundle\Form\Extension
 */
class FormTypeExtension extends AbstractTypeExtension
{
    /**
     * Extends the form type which all other types extend
     *
     * @return string The name of the type being extended
     */
    public function getExtendedType()
    {
        return 'form';
    }

    /**
     * Add the extra row_attr option
     *
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'row_attr' => array()
        ));
    }

    /**
     * Pass the set row_attr options to the view
     *
     * @param FormView $view
     * @param FormInterface $form
     * @param array $options
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['row_attr'] = $options['row_attr'];
    }
}
// src/Acme/FrontendBundle/Form/Extension/FormTypeExtension.php

namespace Acme\FrontendBundle\Form\Extension;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
 * Class FormTypeExtension
 * @package Acme\FrontendBundle\Form\Extension
 */
class FormTypeExtension extends AbstractTypeExtension
{
    /**
     * Extends the form type which all other types extend
     *
     * @return string The name of the type being extended
     */
    public function getExtendedType()
    {
        return FormType::class;
    }

    /**
     * Add the extra row_attr option
     *
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'row_attr' => []
        ));
    }

    /**
     * Pass the set row_attr options to the view
     *
     * @param FormView $view
     * @param FormInterface $form
     * @param array $options
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['row_attr'] = $options['row_attr'];
    }
}
然后我在我的包中注册了服务

<!-- Form row attributes form extension -->
<service id="acme.form_type_extension" class="Acme\FrontendBundle\Form\Extension\FormTypeExtension">
    <tag name="form.type_extension" alias="form" />
</service>
<!-- Form row attributes form extension -->
<service id="acme.form_type_extension" class="Acme\FrontendBundle\Form\Extension\FormTypeExtension">
    <tag name="form.type_extension" alias="form" extended_type="Symfony\Component\Form\Extension\Core\Type\FormType" />
</service>
然后细枝覆盖以使用新的
行属性
选项:

{% block form_row %}
    <div {{ block('form_row_attributes') }}>
        {{ form_label(form) }}
        {{ form_widget(form) }}
        {{ form_errors(form) }}
    </div>
{% endblock form_row %}

{% block form_row_attributes %}
    {% spaceless %}
        {% for attrname, attrvalue in row_attr %}{{ attrname }}="{{ attrvalue }}" {% endfor %}
    {% endspaceless %}
{% endblock form_row_attributes %}
{% block form_row %}
    <div {{ block('form_row_attributes') }}>
        {{ form_label(form) }}
        {{ form_widget(form) }}
        {{ form_errors(form) }}
    </div>
{% endblock form_row %}

{% block form_row_attributes %}
    {% spaceless %}
        {% for attrname, attrvalue in row_attr %}{{ attrname }}="{{ attrvalue }}" {% endfor %}
    {% endspaceless %}
{% endblock form_row_attributes %}

。。但这并不是回答我自己问题的必要条件:P)

以下是@Loppside的答案的克隆,但其变化反映了最新的Symfony结构变化(2.7+):



实际上,这个问题有一个相当简单的解决方案。我只需要一个表单类型扩展来扩展基本表单类型,以允许一个额外的可用选项:

按照文档中的示例,我创建了一个新的表单类型扩展:

// src/Acme/FrontendBundle/Form/Extension/FormTypeExtension.php

namespace Acme\FrontendBundle\Form\Extension;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * Class FormTypeExtension
 * @package Acme\FrontendBundle\Form\Extension
 */
class FormTypeExtension extends AbstractTypeExtension
{
    /**
     * Extends the form type which all other types extend
     *
     * @return string The name of the type being extended
     */
    public function getExtendedType()
    {
        return 'form';
    }

    /**
     * Add the extra row_attr option
     *
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'row_attr' => array()
        ));
    }

    /**
     * Pass the set row_attr options to the view
     *
     * @param FormView $view
     * @param FormInterface $form
     * @param array $options
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['row_attr'] = $options['row_attr'];
    }
}
// src/Acme/FrontendBundle/Form/Extension/FormTypeExtension.php

namespace Acme\FrontendBundle\Form\Extension;

use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
 * Class FormTypeExtension
 * @package Acme\FrontendBundle\Form\Extension
 */
class FormTypeExtension extends AbstractTypeExtension
{
    /**
     * Extends the form type which all other types extend
     *
     * @return string The name of the type being extended
     */
    public function getExtendedType()
    {
        return FormType::class;
    }

    /**
     * Add the extra row_attr option
     *
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'row_attr' => []
        ));
    }

    /**
     * Pass the set row_attr options to the view
     *
     * @param FormView $view
     * @param FormInterface $form
     * @param array $options
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['row_attr'] = $options['row_attr'];
    }
}
然后我在我的包中注册了服务

<!-- Form row attributes form extension -->
<service id="acme.form_type_extension" class="Acme\FrontendBundle\Form\Extension\FormTypeExtension">
    <tag name="form.type_extension" alias="form" />
</service>
<!-- Form row attributes form extension -->
<service id="acme.form_type_extension" class="Acme\FrontendBundle\Form\Extension\FormTypeExtension">
    <tag name="form.type_extension" alias="form" extended_type="Symfony\Component\Form\Extension\Core\Type\FormType" />
</service>
然后细枝覆盖以使用新的
行属性
选项:

{% block form_row %}
    <div {{ block('form_row_attributes') }}>
        {{ form_label(form) }}
        {{ form_widget(form) }}
        {{ form_errors(form) }}
    </div>
{% endblock form_row %}

{% block form_row_attributes %}
    {% spaceless %}
        {% for attrname, attrvalue in row_attr %}{{ attrname }}="{{ attrvalue }}" {% endfor %}
    {% endspaceless %}
{% endblock form_row_attributes %}
{% block form_row %}
    <div {{ block('form_row_attributes') }}>
        {{ form_label(form) }}
        {{ form_widget(form) }}
        {{ form_errors(form) }}
    </div>
{% endblock form_row %}

{% block form_row_attributes %}
    {% spaceless %}
        {% for attrname, attrvalue in row_attr %}{{ attrname }}="{{ attrvalue }}" {% endfor %}
    {% endspaceless %}
{% endblock form_row_attributes %}
。。但这并不是回答我自己问题的必要条件:P)

我所做的比较简单(尽管可能有点不干净?)

通过字段的“数据”属性传递表单行的类:

// template.html.twig

{{ form_start(form) }}
    {{ form_row(form.field, {'attr': {'data-row-class': 'my-row-class'} }) }}
{{ form_end(form) }}
然后在表单主题模板中按以下方式进行处理:

// form-theme.html.twig

{% block form_row -%}
    {% set row_class = attr['data-row-class'] | default('') %}
    <div class="{{ row_class }}">
        {{- form_label(form) -}}
        {{- form_widget(form) -}}
        {{- form_errors(form) -}}
    </div>
{%- endblock form_row %}
//form-theme.html.twig
{%block form_row-%}
{%set row_class=attr['data-row-class']|默认值('')%}
{{-form_标签(form)-}
{{-form_小部件(form)-}
{{-form_错误(form)-}
{%-endblock form_row%}
因此:

<form name="formName" method="post">
    <div class="my-row-class">
        <label for="formName_field">Field label</label>
        <input type="text" id="formName_field" name="formName[field]" data-row-class="my-row-class">
    </div>
</form>

字段标签

这只允许您将
attr
传递给表单、标签、小部件、错误,而不是行。事实上,如果您查看原始主题文件(
form\u div\u layout.html.twig
),您可以看到在
form\u行
块中,周围的
将永远不会注入任何传递的变量。。。因此,我的问题是如何做到这一点。谢谢你的建议。@Loppside,你是对的,那么只有一个选项-根据模板中的需要重写form_row。是的,我已经得到了
form_row
重写,但是我需要一半的行使用一个版本,另一半使用另一个版本和额外的
form row split
类。除了它们都使用相同的
form\u row
覆盖块之外-因此我需要能够以某种方式将某些内容传递到此覆盖块中…为什么不在css文件中实现
div.form-row-split
label.form row split
input.form row split
,而不是在表单生成中找到黑客?是的!谢谢@lopsided这对我现在非常有帮助,非常好的回答(和问题):)你知道如何使用重复的打字形式轻松地完成这项工作吗?