Symfony 6 - Fail to inject data into a dynamic formtype on POST_SUBMIT

Viewed 97

I have a problem with a nested form. I can't get the values I want to pass. Here is a simple example to reproduce my problem, I would like to pre-fill a form about a user according to the selected house in my form.
Here are the files, if you want to test. I would like to inject the values of roger and billy the good way but my user fields are always empty

The models

class Test
{
    /**
     * @var string|null
     */
    private $house;

    /**
     * @var TestUser|null
     */
    private $user;

    // Getters & Setters of course...   
}
class TestUser
{
    /**
     * @var string|null
     */
    private $name;

    /**
     * @var int|null
     */
    private $age;

    // Getters & Setters again...
}

The main form

class TestType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('house', ChoiceType::class, [
                    'choices' => [
                        'first'  => 1,
                        'second' => 2,
                    ],
                ]
            );

        $builder->get('house')->addEventListener(FormEvents::POST_SUBMIT, [$this, 'addUser']);
    }


    function addUser(FormEvent $event)
    {
        $form  = $event->getForm()->getParent();
        $house = $event->getForm()->getData();

        if (!$house) {
            return;
        }

        // here is the part where I choose the user I want to use 
        // for the rest of the example (which does not work)
        $testUser = $house === 1
            ? (new TestUser())->setName('roger')->setAge(65)
            : (new TestUser())->setName('billy')->setAge(22);

        $builder = $form->getConfig()->getFormFactory()->createNamedBuilder('user', TestUserType::class, $testUser, [
            'auto_initialize' => false,
        ]);

        $form->add($builder->getForm());
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => Test::class,
        ]);
    }
}

The user form type

class TestUserType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('name', TextType::class, ['label' => 'username'])
            ->add('age', IntegerType::class, ['label' => 'age']);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class' => TestUser::class,
        ]);
    }
}

The controller

public function testForm(Request $request): RedirectResponse|Response
{
    // ...
    $test = new Test();
    $form = $this->createForm(TestType::class, $test);
    $form->handleRequest($request);
    // ...
}

The view

{{ form_start(formtest) }}
  <p>
    <button class="btn btn-primary" type="submit">test go</button>
  </p>
{{ form_end(formtest) }}

all help is welcome

2 Answers

Is setter actually returning $this?

When ->setAge(65) is executed.

Because it's not clear, it's not in your code you provided here.

you need to link the $user $age $house and $name to the input fields you have. The reason why you always get an empty output is do to the face that non of the variables refer to any data source.

Related