symfony 4 中的表单生成器和主题变量
Form builder and theming variables in symfony 4
有些情况下我的表单输入会有图标,有些则没有。最初,我以为我可以像这样将 class 放在表单生成器中:
$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.'
])
]
])
然后表单模板中的输出可能会采用 class 并重新配置外观。显然这行不通,但这是我前进的方向:
{% 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 %}
这是正确的方法还是有其他更可靠的方法?
编辑 2019 年 9 月 22 日
我想做一个测试,这很有趣,因为如果我要尝试访问表单的块前缀,我可以像这样在表单主题中指定:
block_prefixes.2 == "password"
这将访问块前缀内的数组并检查它。但是,如果我要访问 attr,那么 class 选项如下所示:
attr.class
它会 return 一个错误 Key "class" does not exist as the array is empty.
这是为什么?如何轻松访问 attr 中的数组?
我认为您想为每个输入创建一个自定义 FormType,然后在您的主题中为每个输入使用一个自定义 fom_widget,就像在内置 Symfony\Component\Form\Extension\Core\Type\PercentType
和 [=13= 中所做的一样]
表格类型:
// 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';
}
}
form_theme:
// 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 %}
...
您当前的方法可行。您只需要获取表单的正确子项的变量,而不是整个表单。这应该有效(在本例中为 电子邮件):
{% if form.email.vars.attr.class == 'has_icon icon_email' %}
do or show something here
{% endif %}
或者简单地测试你的单身 class has_icon
:
{% if 'has_icon' in form.email.vars.attr.class %}
do or show something here
{% endif %}
对于您在评论中描述的 any field 字段,我想您需要遍历所有表单子项并查看它们是否包含您正在测试的 class为了。像这样:
{% for input in form.children %}
{% if 'has_icon' in input.vars.attr.class | default %}
do or show something here
{% endif %}
{% endfor %}
| default
适用于没有 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'];
}
}
?>
现在在生成器中我可以应用图标选项(由于我的扩展,它默认为空,所以在表单生成器不使用它的情况下):
$builder
->add('email', EmailType::class, [
'label' => 'Email address',
'attr' => [
'placeholder' => 'john.smith@foo.com'
],
'constraints' => [
new NotBlank([
'message' => 'Enter an email address.'
])
],
"icon" => "icon_email"
])
现在我可以在我的表单主题中访问该信息,例如 {% if icon != null %}
现在我可以根据自己的喜好对其进行自定义。
还要声明我更喜欢 Symfony 4 因为它的强大!干杯,希望这对其他人有帮助。
有些情况下我的表单输入会有图标,有些则没有。最初,我以为我可以像这样将 class 放在表单生成器中:
$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.'
])
]
])
然后表单模板中的输出可能会采用 class 并重新配置外观。显然这行不通,但这是我前进的方向:
{% 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 %}
这是正确的方法还是有其他更可靠的方法?
编辑 2019 年 9 月 22 日
我想做一个测试,这很有趣,因为如果我要尝试访问表单的块前缀,我可以像这样在表单主题中指定:
block_prefixes.2 == "password"
这将访问块前缀内的数组并检查它。但是,如果我要访问 attr,那么 class 选项如下所示:
attr.class
它会 return 一个错误 Key "class" does not exist as the array is empty.
这是为什么?如何轻松访问 attr 中的数组?
我认为您想为每个输入创建一个自定义 FormType,然后在您的主题中为每个输入使用一个自定义 fom_widget,就像在内置 Symfony\Component\Form\Extension\Core\Type\PercentType
和 [=13= 中所做的一样]
表格类型:
// 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';
}
}
form_theme:
// 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 %}
...
您当前的方法可行。您只需要获取表单的正确子项的变量,而不是整个表单。这应该有效(在本例中为 电子邮件):
{% if form.email.vars.attr.class == 'has_icon icon_email' %}
do or show something here
{% endif %}
或者简单地测试你的单身 class has_icon
:
{% if 'has_icon' in form.email.vars.attr.class %}
do or show something here
{% endif %}
对于您在评论中描述的 any field 字段,我想您需要遍历所有表单子项并查看它们是否包含您正在测试的 class为了。像这样:
{% for input in form.children %}
{% if 'has_icon' in input.vars.attr.class | default %}
do or show something here
{% endif %}
{% endfor %}
| default
适用于没有 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'];
}
}
?>
现在在生成器中我可以应用图标选项(由于我的扩展,它默认为空,所以在表单生成器不使用它的情况下):
$builder
->add('email', EmailType::class, [
'label' => 'Email address',
'attr' => [
'placeholder' => 'john.smith@foo.com'
],
'constraints' => [
new NotBlank([
'message' => 'Enter an email address.'
])
],
"icon" => "icon_email"
])
现在我可以在我的表单主题中访问该信息,例如 {% if icon != null %}
现在我可以根据自己的喜好对其进行自定义。
还要声明我更喜欢 Symfony 4 因为它的强大!干杯,希望这对其他人有帮助。