如何在Symfony 3中设置默认表单所需的状态(并在构建器中覆盖)?



我正在尝试构建一个表单并将默认的"必需"状态设置为 false, 然后让表单构建配置覆盖它,将一些设置为 true。

如果我不添加配置选项,则字段默认为"必需"为true,我可以使用特定配置覆盖它们。

但是,如果我添加:

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('required', false);
}

我无法在特定配置中覆盖它(这并不要求为真(:

->add('name',TextType::class, array(
'required' => true,
'constraints' => array(new Length(array('min' => 3)))
))

有没有办法做到这一点,或者我必须始终不设置默认值并指定每个配置?

这可以通过PRE_SET_DATASymfony表单事件来实现。 本质上,您所要做的就是在该表单事件中重新添加所有表单字段。 当您在表单事件中添加它们时,它们将覆盖您现有的同名表单域。 您希望重新添加所有信息相同的字段,同时替换表单选项数组并手动将所需选项设置为false。 看一看:

class MyType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(/* ... */)
->add(/* ... */)
;
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
// loop through each form field
foreach ($form->all() as $field) {
$config  = $field->getConfig();
$options = $config->getOptions();
// re-add the form field and overwrite the 'required' option
// this overwrites the existing field
$form->add(
$field->getName(),
get_class($config->getType()->getInnerType()),
array_replace($options, ['required' => false])
);
}
});
}
}

请注意以下行:

get_class($config->getType()->getInnerType()),

应该改为

$config->getType()->getName()

如果您使用的是早于 Symfony 3 的 Symfony 版本。

作为一些背景,根据设计,FormConfigInterface接口不允许在配置设置后进行修改。 如果你看一眼里面,它只有gethas功能 - 所以不能手动设置任何东西。 添加表单/表单字段时必须完成。

如果您希望在整个项目中实现全局化,则可以创建一个在buildForm()事件中包含此功能的基本窗体类型,然后所有子窗体都可以在设置自身后调用父窗体。 您也可以对单个字段执行此操作 - 而不是循环使用

foreach ($form->all() as $field) {

您可以简单地更改特定字段

$config = $form->get('field_name');
$options = $config->getOptions();
$form->add(
'field_name',
get_class($config->getType()->getInnerType()),
array_replace($options, ['required' => false])
);

此表单扩展(请参阅 http://symfony.com/doc/master/form/create_form_type_extension.html(允许您默认所有表单的所有字段,并带有required=false

// src/AppBundle/Form/Extension/RequiredDefaultsToFalseExtension.php
<?php
namespace AppBundleFormExtension;
use SymfonyComponentFormAbstractTypeExtension;
use SymfonyComponentFormExtensionCoreTypeFormType;
use SymfonyComponentOptionsResolverOptionsResolver;
class RequiredDefaultsToFalseExtension extends AbstractTypeExtension
{
/**
* Returns the name of the type being extended.
*
* @return string The name of the type being extended
*/
public function getExtendedType()
{
return FormType::class;
}
/**
*
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('required', false);
}
}

必须注册扩展

# app/config/services.yml
services:
app.required_defaults_to_false_extension:
class: AppBundleFormExtensionRequiredDefaultsToFalseExtension
tags:
- { name: form.type_extension, extended_type: SymfonyComponentFormExtensionCoreTypeFormType }         

你完成了,你什么也不需要做。

请记住,required选项仅在表单(http://symfony.com/doc/current/reference/forms/types/form.html#required(的视图中起作用,但empty_data选项(http://symfony.com/doc/current/reference/forms/types/form.html#empty-data(有一些反映,您也可以使用此扩展名而不是前一个扩展名(也许您必须调整它以完全满足您的需求(

// src/AppBundle/Form/Extension/RootFormRequiredDefaultsToFalseExtension.php
<?php
namespace AppBundleFormExtension;
use SymfonyComponentFormAbstractTypeExtension;
use SymfonyComponentFormExtensionCoreTypeFormType;
use SymfonyComponentFormFormInterface;
use SymfonyComponentFormFormView;
use SymfonyComponentOptionsResolverOptionsResolver;
class RootFormRequiredDefaultsToFalseExtension extends AbstractTypeExtension
{
/**
* Returns the name of the type being extended.
*
* @return string The name of the type being extended
*/
public function getExtendedType()
{
return FormType::class;
}
/**
*
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefault('root_form_required_defaults_to_false', false);
}
public function buildView(FormView $view, FormInterface $form, array $options)
{
if ($form->getParent()) {
if ($form->getParent()->getConfig()->getOption('root_form_required_defaults_to_false')) {
$view->vars['required']=false;
}
}
}
}

必须注册扩展

# app/config/services.yml
services:
app.root_form_required_defaults_to_false_extension:
class: AppBundleFormExtensionRootFormRequiredDefaultsToFalseExtension
tags:
- { name: form.type_extension, extended_type: SymfonyComponentFormExtensionCoreTypeFormType }   

在要使用它的表单类型中,您必须启用它

// src/AppBundle/Form/MyFormType.php
// ..
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
// ..
'root_form_required_defaults_to_false'=>true
));
}

最后,请记住,您可以使用在根表单选项或树枝视图中设置此属性,在每个表单的基础上禁用 html5 验证。(http://symfony.com/doc/master/forms.html#form-validation(

// src/AppBundle/Form/MyFormType.php
// ..
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
// ..
'attr' => ['novalidate'=>'novalidate'],
));

最新更新