Twig symfony 4中的表单生成器和主题化变量

Twig symfony 4中的表单生成器和主题化变量,twig,symfony4,Twig,Symfony4,有些情况下,我的表单输入会有图标,有些则没有。最初,我认为我可以将该类放在form builder中,如下所示: $builder ->add('email', EmailType::class, [ 'label' => 'Email address', 'attr' => [ 'placeholder' => 'john.smith@foo.com',

有些情况下,我的表单输入会有图标,有些则没有。最初,我认为我可以将该类放在form builder中,如下所示:

$builder
        ->add('email', EmailType::class, [
            'label' => 'Email address',
            'attr' => [
                'placeholder' => 'john.smith@foo.com',
                'class' => 'has_icon icon_email'
            ],
            'constraints' => [
                new NotBlank([
                    'message' => 'Enter an email address.'
                ])
            ]
        ])
然后表单模板中的输出可能会接受该类并重新配置外观。显然这不起作用,但这是我的方向:

{% block form_row %}
    <div class="form_row">
        {{ form_label(form) }}
        {% if form.vars.attr.class == 'has_icon' %}
            test
        {% endif %}
        {{ form_errors(form) }}
    </div>
{% endblock form_row %}
{%block form_row%}
{{form_标签(form)}
{%if form.vars.attr.class='具有\u图标“%”
测试
{%endif%}
{{form_errors(form)}}
{%endblock form_row%}
这是正确的方法还是有其他更可靠的方法


编辑2019年9月22日

我想做一个测试,这很有趣,因为如果我试图访问表单的块前缀,我可以在表单主题中指定如下内容:

block_前缀。2==“password”
这将访问块前缀中的数组并检查它。但是,如果要访问attr,则类选项如下:


attr.class
它将返回一个错误
键“class”不存在,因为数组为空。
为什么?如何方便地访问attr中的数组?

我认为您希望为每个输入创建一个自定义FormType,然后为主题中的每个输入使用一个自定义fom_小部件,就像在内置的
Symfony\Component\Form\Extension\Core\Type\PercentType
bootstrap\u 4\u layout.html.twig中所做的那样

表单类型:

// src:"/vendor/symfony/form/Extension/Core/Type/PercentType.php"

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;

class PercentType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addViewTransformer(new PercentToLocalizedStringTransformer($options['scale'], $options['type']));
    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['symbol'] = $options['symbol'];
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'scale' => 0,
            'symbol' => '%',
            'type' => 'fractional',
            'compound' => false,
        ]);

        $resolver->setAllowedValues('type', [
            'fractional',
            'integer',
        ]);

        $resolver->setAllowedTypes('scale', 'int');
        $resolver->setAllowedTypes('symbol', ['bool', 'string']);
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'percent';
    }
}
// src:"/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_4_layout.html.twig"
...

{% block percent_widget -%}
    {%- if symbol -%}
        <div class="input-group">
            {{- block('form_widget_simple') -}}
            <div class="input-group-append">
                <span class="input-group-text">{{ symbol|default('%') }}</span>
            </div>
        </div>
    {%- else -%}
        {{- block('form_widget_simple') -}}
    {%- endif -%}
{%- endblock percent_widget %}

...
形成主题:

// src:"/vendor/symfony/form/Extension/Core/Type/PercentType.php"

namespace Symfony\Component\Form\Extension\Core\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;

class PercentType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addViewTransformer(new PercentToLocalizedStringTransformer($options['scale'], $options['type']));
    }

    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['symbol'] = $options['symbol'];
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'scale' => 0,
            'symbol' => '%',
            'type' => 'fractional',
            'compound' => false,
        ]);

        $resolver->setAllowedValues('type', [
            'fractional',
            'integer',
        ]);

        $resolver->setAllowedTypes('scale', 'int');
        $resolver->setAllowedTypes('symbol', ['bool', 'string']);
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'percent';
    }
}
// src:"/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_4_layout.html.twig"
...

{% block percent_widget -%}
    {%- if symbol -%}
        <div class="input-group">
            {{- block('form_widget_simple') -}}
            <div class="input-group-append">
                <span class="input-group-text">{{ symbol|default('%') }}</span>
            </div>
        </div>
    {%- else -%}
        {{- block('form_widget_simple') -}}
    {%- endif -%}
{%- endblock percent_widget %}

...
//src:“/vendor/symfony/twig bridge/Resources/views/Form/bootstrap\u 4\u layout.html.twig”
...
{%block percent\小部件-%}
{%-if符号-%}
{{-block('form_widget_simple')-}
{{symbol}默认值('%')}
{%-else-%}
{{-block('form_widget_simple')-}
{%-endif-%}
{%-endblock%_widget%}
...

您当前的方法可能有效。您只需要获取表单的正确子级的变量,而不是整个表单。这应该是有效的(在本例中是在电子邮件上)

{% if form.email.vars.attr.class == 'has_icon icon_email' %}
    do or show something here
{% endif %}
或者简单地测试您的单个类
有\u图标

{% if 'has_icon' in form.email.vars.attr.class %}
    do or show something here
{% endif %} 
对于您在注释中描述的任何字段,我想您需要迭代所有表单子项,看看它们是否包含您要测试的类。大概是这样的:

{% for input in form.children  %}
    {% if 'has_icon' in input.vars.attr.class | default %}
        do or show something here
    {% endif %}
{% endfor %}

对于没有class属性的字段,
|默认值
。另外,我建议您在同一次迭代中渲染输入字段,这样您就可以在正确的位置渲染图标。我希望这会让你开始

我明白了。因为从全局角度来看,图标将在我的应用程序中使用

方法是首先扩展
FormType
,在我的例子中,它被称为
FormTypeExtension
,它被放置在这个层次结构中:
src/Form/Extensions/FormTypeExtension.php

该文件概述了:

<?php

namespace App\Form\Extension;

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

class FormTypeExtension extends AbstractTypeExtension
{
    public static function getExtendedTypes() : iterable
    {
        return [FormType::class];
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'icon' => null
        ]);
    }

    public function buildView(FormView $view, FormInterface $form, array $options)
    {

        $view->vars['icon'] = $options['icon'];
    }
}

?>
现在我可以在我的表单主题中访问这些信息,比如
{%if icon!=null%}
现在我可以根据自己的喜好对其进行自定义


我还要说,我更喜欢Symfony 4,因为它是多么强大!干杯,希望这有助于其他人。

javascript和/或cssUh,但对于表单字段,您不能仅“将图标应用于输入”-输入不允许:before/:after伪。如果我是从JS端这样做的话,这将为每个输入创建一个显著的命中率。我觉得这似乎不是正确的解决方案?这是唯一的解决方案吗?你使用什么类型的图标?嗯。。。不确定这样做是否正确?因为如果我想要一个密码字段有一个图标,或者一个数字,文本,等等,这不会引起额外的工作吗?这就是Symfony的方式。我向您展示的是直接来自Symfony源文件的内容。这是否意味着我必须检查每个表单变量实例?有没有办法只检查任何输入是否有“has_icon”类,这样我就不必在每次创建has_icon的新实例时手动更新它?只需查看我给出答案的最后一段代码。这就可以在课堂上的任何地方检查“has_icon”。是的,但这是专门针对表单中的“email”,而不是针对任何输入元素的空白列表。这意味着,如果我有多个需要图标的输入,我必须手动更新每个输入,这对我来说似乎很可笑。我以为你会单独渲染所有字段,因为代码中有
表单行
,所以你是说你只想渲染整个表单?对不起,我不完全清楚你想达到什么目的。