Home > OS >  Symfony 4 PRE_SET_DATA Event Listener setData not updating custom type fields
Symfony 4 PRE_SET_DATA Event Listener setData not updating custom type fields

Time:09-23

I have a parent form type which includes an unmapped child form type. The child form type contains three ChoiceType fields which are populated manually due to a specific formatting requirement.

The fields load correctly and saving of the data from the ChoiceType fields is handled with no issue.

The problem I'm having is, because the ChoiceType fields in the child need to be populated using data from the parent, I am trying to manually populate/set the default values of those fields using a PRE_SET_DATA event listener on the parent - the event listener is being called and fields are updated using setData but, once the form loads, the ChoiceType fields are still empty.

I've tested manually setting the data property within the ChoiceType fields to the same value as is being set within the event listener and this works correctly, so the issue is definitely with the setData call.

An example:

class ParentType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('child_field', ChildType::class, [
                'required' => false,
                'mapped'   => false,
                'label'    => false
            ])
            ->add('save', SubmitType::class, [
                'attr' => [
                    'class' => 'save',
                ],
            ])
            ->addEventSubscriber(new FormLoadedListener());
    }

    ...
}

class ChildType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('first_field', ChoiceType::class, [
                'required'  => false,
                'label'     => 'First Field',
                'choices'   => $this->buildFirstChoices(),
            ])
            ->add('second_field', ChoiceType::class, [
                'required'  => false,
                'label'     => 'Second Field',
                'choices'   => $this->buildSecondChoices(),
            ])
            ->add('third_field', ChoiceType::class, [
                'required'  => false,
                'label'     => 'Third Field',
                'choices'   => $this->buildThirdChoices(),
            ]);
    }
}

class FormLoadedListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            FormEvents::PRE_SET_DATA => 'onPreSetData'
        ];
    }

    public function onPreSetData(FormEvent $event): void
    {
        $data = $event->getData();
        $form = $event->getForm();
        
        $firstValue = $this->doStuffToGetFirstValue();
        $secondValue = $this->doStuffToGetSecondValue();
        $thirdValue = $this->doStuffToGetThirdValue();

        $childField = $form->get('child_field');

        $childField->get('first_field')->setData($firstValue);
        $childField->get('second_field')->setData($secondValue);
        $childField->get('third_field')->setData($thirdValue);
    }

I've also tried other methods to set the data:

$form->get('child_field')->setData([
    'first_field' => $firstValue,
    'second_field' => $secondValue,
    'third_field' => $thirdValue
]);

And

$form->setData(['child_field' => [
    'first_field' => $firstValue,
    'second_field' => $secondValue,
    'third_field' => $thirdValue
]);

CodePudding user response:

It turns out I was using the incorrect event listener. The data was being set but was being overridden by null values - I instead had to use FormEvents::POST_SET_DATA which fixed the issue

  • Related