如何动态更改 symfony2 表单字段的选项?
How to change option dynamically for a symfony2 form field?
在 symfony 2.5.6 中,
如何以 symfony2 形式动态更改选项,例如:
// src/AppBundle/Form/Type/TaskType.php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class TaskType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('task')
->add('dueDate', null, array('widget' => 'single_text'))
->add('save', 'submit');
if (condition) {
//how to change option of 'task' or 'dueDate' by example
//something like this, but addOption doesn't exist and i don't find any usefull method
$builder->get('dueDate')->addOption('read_only', true)
}
}
public function getName()
{
return 'task';
}
}
需要使用事件吗?
http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html
或者这个[=3=]
foreach($builder->all() as $key => $field) {
if ($key == 'dueDate')) {
$options = $field->getOptions();
$options = array_merge_recursive($options, array('read_only' => true));
$builder->remove($key);
$builder->add($key, $field->getName(), $options);
}
}
#with 'Could not load type "dueDate"' error when i display my form in a browser!
怎么办?最佳做法?
谢谢!
我不知道你所说的 'best practice' 是什么意思,但为什么不这样做:
$builder
->add('dueDate', null, array('widget' => 'single_text'))
->add('save', 'submit');
$options = [
KEY => VALUE,
....
];
if (condition) {
$options = [
ANOTHER_KEY => ANOTHER_VALUE,
....
];
}
$builder->add('task', TYPE, $options);
另一种方法是使用 PRE_SUBMIT
事件,像这样..
$builder
->add('task')
->add('dueDate', null, array('widget' => 'single_text'))
->add('save', 'submit');
$builder->addEventListener(FormEvents::PRE_SUBMIT, [$this, 'preSubmit']);
....
public function preSubmit(FormEvent $event)
{
if (CONDITION) {
$builder->remove('task');
$builder->add('task', TYPE, $NEW_OPTIONS_ARRAY);
}
}
我使用此功能在将字段添加到表单后更新选项。它基本上意味着用我们拥有的数据重新生成字段,向选项添加一些内容并重新添加字段,重新添加其转换器等等
将此辅助函数放在 FormHelper 的某处 class,或任何你喜欢的地方
/**
* @param FormBuilderInterface $builder
* @param string $fieldName
* @param string $optionName
* @param $optionData
*/
public static function setOptionToExistingFormField(
FormBuilderInterface $builder,
string $fieldName,
string $optionName,
$optionData
): void {
if (!$builder->has($fieldName)) {
// return or throw exception as you wish
return;
}
$field = $builder->get($fieldName);
// Get some things from the old field that we also need on the new field
$modelTransformers = $field->getModelTransformers();
$viewTransformers = $field->getViewTransformers();
$options = $field->getOptions();
$fieldType = get_class($field->getType()->getInnerType());
// Now set the new option value
$options[$optionName] = $optionData;
/**
* Just use "add" again, if it already exists the existing field is overwritten.
* See the documentation of the add() function
* Even the position of the field is preserved
*/
$builder->add($fieldName, $fieldType, $options);
// Reconfigure the transformers (if any), first remove them or we get some double
$newField = $builder->get($fieldName);
$newField->resetModelTransformers();
$newField->resetViewTransformers();
foreach($modelTransformers as $transformer) {
$newField->addModelTransformer($transformer);
}
foreach($viewTransformers as $transformer) {
$newField->addViewTransformer($transformer);
}
}
然后像这样使用
$builder
->add('someField', SomeSpecialType::class, [
'label' => false,
])
;
FormHelper::setOptionToExistingFormField($builder, 'someField', 'label', true);
在 symfony 2.5.6 中, 如何以 symfony2 形式动态更改选项,例如:
// src/AppBundle/Form/Type/TaskType.php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
class TaskType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('task')
->add('dueDate', null, array('widget' => 'single_text'))
->add('save', 'submit');
if (condition) {
//how to change option of 'task' or 'dueDate' by example
//something like this, but addOption doesn't exist and i don't find any usefull method
$builder->get('dueDate')->addOption('read_only', true)
}
}
public function getName()
{
return 'task';
}
}
需要使用事件吗?
http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html
或者这个[=3=]
foreach($builder->all() as $key => $field) {
if ($key == 'dueDate')) {
$options = $field->getOptions();
$options = array_merge_recursive($options, array('read_only' => true));
$builder->remove($key);
$builder->add($key, $field->getName(), $options);
}
}
#with 'Could not load type "dueDate"' error when i display my form in a browser!
怎么办?最佳做法?
谢谢!
我不知道你所说的 'best practice' 是什么意思,但为什么不这样做:
$builder
->add('dueDate', null, array('widget' => 'single_text'))
->add('save', 'submit');
$options = [
KEY => VALUE,
....
];
if (condition) {
$options = [
ANOTHER_KEY => ANOTHER_VALUE,
....
];
}
$builder->add('task', TYPE, $options);
另一种方法是使用 PRE_SUBMIT
事件,像这样..
$builder
->add('task')
->add('dueDate', null, array('widget' => 'single_text'))
->add('save', 'submit');
$builder->addEventListener(FormEvents::PRE_SUBMIT, [$this, 'preSubmit']);
....
public function preSubmit(FormEvent $event)
{
if (CONDITION) {
$builder->remove('task');
$builder->add('task', TYPE, $NEW_OPTIONS_ARRAY);
}
}
我使用此功能在将字段添加到表单后更新选项。它基本上意味着用我们拥有的数据重新生成字段,向选项添加一些内容并重新添加字段,重新添加其转换器等等
将此辅助函数放在 FormHelper 的某处 class,或任何你喜欢的地方
/**
* @param FormBuilderInterface $builder
* @param string $fieldName
* @param string $optionName
* @param $optionData
*/
public static function setOptionToExistingFormField(
FormBuilderInterface $builder,
string $fieldName,
string $optionName,
$optionData
): void {
if (!$builder->has($fieldName)) {
// return or throw exception as you wish
return;
}
$field = $builder->get($fieldName);
// Get some things from the old field that we also need on the new field
$modelTransformers = $field->getModelTransformers();
$viewTransformers = $field->getViewTransformers();
$options = $field->getOptions();
$fieldType = get_class($field->getType()->getInnerType());
// Now set the new option value
$options[$optionName] = $optionData;
/**
* Just use "add" again, if it already exists the existing field is overwritten.
* See the documentation of the add() function
* Even the position of the field is preserved
*/
$builder->add($fieldName, $fieldType, $options);
// Reconfigure the transformers (if any), first remove them or we get some double
$newField = $builder->get($fieldName);
$newField->resetModelTransformers();
$newField->resetViewTransformers();
foreach($modelTransformers as $transformer) {
$newField->addModelTransformer($transformer);
}
foreach($viewTransformers as $transformer) {
$newField->addViewTransformer($transformer);
}
}
然后像这样使用
$builder
->add('someField', SomeSpecialType::class, [
'label' => false,
])
;
FormHelper::setOptionToExistingFormField($builder, 'someField', 'label', true);