Symfony: [Form] [3.0] setData в FormEvents :: SUBMIT не работает в составных формах

Созданный на 12 мая 2016  ·  3Комментарии  ·  Источник: symfony/symfony

Если у вас есть составная форма и вы вызываете 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, по-прежнему имеет пустое значение, поэтому, если вы при рендеринге формы поле имени остается пустым.

Bug Form Needs Review Unconfirmed

Самый полезный комментарий

Я могу воспроизвести это, но это не ошибка. Это немного сложно объяснить, скажем, дети уже сдаются раньше.

у вас есть два варианта решения:

  • Добавьте событие в подтип, например
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name')
        ;

        $builder
            ->get('name')
            ->addEventSubscriber($this);
    }
  • Используйте PRE_SUBMIT из событий формы

Я надеюсь, это поможет вам

Все 3 Комментарий

Подводя итог: изменение данных с помощью 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). Это поможет понять, когда срабатывает какое событие в какой форме (родительской или дочерней).

Была ли эта страница полезной?
0 / 5 - 0 рейтинги