Если у вас есть составная форма и вы вызываете setData()
с измененными данными внутри слушателя для FormEvents::SUBMIT
данные не изменяются правильно. Когда функция handleRequest()
завершена, данные normdata, viewdata и modeldata составной формы верны, но значения дочерних форм не изменились. Если после этого вы вызовете $form->createView()
форма не будет содержать изменений.
Пример кода для воспроизведения ошибки:
Контроллер:
public function newAction(Request $request)
{
$form = $this->createForm(FormName::class);
$form->handleRequest($request);
return $this->render(
"AppBundle:Default:form.html.twig",
[
'form' => $form->createView()
]
);
}
Форма:
class FeatureType extends AbstractType implements EventSubscriberInterface
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->addEventSubscriber($this)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(['data_class' => 'Cat\AppBundle\PlainClasses\Form\FeatureDTO']);
}
public static function getSubscribedEvents()
{
return [
FormEvents::SUBMIT => 'submit'
];
}
public function submit(FormEvent $event)
{
$data = $event->getData();
$data->name = 'test';
$event->setData($data);
}
}
DTO:
class FeatureDTO
{
/**
* <strong i="18">@var</strong> string
*/
public $name;
}
С помощью этого кода вы увидите, что данные normdata, viewdata и modeldata полной формы featureType обновлены, а имя установлено на 'test', но дочерняя форма, форма имени, которая является TextType, по-прежнему имеет пустое значение, поэтому, если вы при рендеринге формы поле имени остается пустым.
Подводя итог: изменение данных с помощью setData
действительно изменяет данные, но это изменение не распространяется на дочерние элементы. Таким образом, после рендеринга формы поля формы все еще имеют старые значения.
Я могу воспроизвести это, но это не ошибка. Это немного сложно объяснить, скажем, дети уже сдаются раньше.
у вас есть два варианта решения:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
;
$builder
->get('name')
->addEventSubscriber($this);
}
PRE_SUBMIT
из событий формыЯ надеюсь, это поможет вам
Я уже ожидал, что представление детей уже обработано. Я не могу использовать первый вариант, потому что хочу изменить другое поле (например, «возраст»), которое находится на том же уровне, что и «имя». Поэтому, если я обрабатываю событие по имени, я не могу изменить данные другого поля, а затем имя, AFAIK.
Тогда мне придется перейти ко второму варианту. Затем я должен сам разрешить некоторые объекты, которые были бы разрешены автоматически, если бы я мог использовать событие SUBMIT.
IMHO было бы очень полезно добавить расширенный рабочий процесс с дочерними формами на страницу событий формы в книге рецептов (http://symfony.com/doc/current/components/form/form_events.html). Это поможет понять, когда срабатывает какое событие в какой форме (родительской или дочерней).
Самый полезный комментарий
Я могу воспроизвести это, но это не ошибка. Это немного сложно объяснить, скажем, дети уже сдаются раньше.
у вас есть два варианта решения:
PRE_SUBMIT
из событий формыЯ надеюсь, это поможет вам