0
votes

I have a function that generate a form for each 'joueur' :

public function new(Request $oRequest): Response
{
    $played = new Played();

    $em = $this->getDoctrine()->getManager();
    $lastTourn = $em->getRepository(Tournoi::class)->findOneBy([], ['id' => 'desc']);
    $disputeds = $lastTourn->getDisputeds();
    foreach($disputeds as $d){
        $joueurs[] = $d->getJoueur();
    }

    foreach ($joueurs as $j) 
    {
        $sUniqueFormName = 'Form' . $j->getId(); 
        $oForm = $this->get('form.factory')->createNamed($sUniqueFormName, PlayedType::class, $played);
        $aForms[$sUniqueFormName] = $oForm;
    }

    foreach ($aForms as $sFormName => $oForm)
    {
        $oForm->handleRequest($oRequest);
        if ($oForm->isSubmitted() && $oForm->isValid())
        {
            //flush
        }

        $aFormViews[$sFormName] = $oForm->createView(); 
    }

    return $this->render('played/new.html.twig', [
        'played' => $played,
        'joueurs' => $joueurs,
        'formulaires' => $aFormViews,
    ]);

Then, a manage to render the array of forms in one Twig view :

<h1>Create new Played</h1>

{% for form in formulaires %}
    {{ joueurs[loop.index0].nom }}
    {{ form_start(form) }}
        {{ form_row(form.max) }}
        {{ form_row(form.score) }}
        {{ form_row(form.points) }}
{% endfor %}
<input type="submit" formaction="{{ path('played_new') }}" value="Envoyer le formulaire">

The question is, how can I submit all this forms in one submit button ?

And then, How I manage all the forms data to persist the Entity ?

Here you have my database relations :

Database

Form Class :

class PlayedType extends AbstractType {
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            /*->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
            $form = $event->getForm();
            $form->add('joueur', null, array(
                 'data' => $event->getData() ?: options['joueur']
             ))*/
            ->add('max')
            ->add('score')
            ->add('points')
            ;
        //});
    }

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

class PlayedScoreType extends AbstractType {
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            //->add('nom')
            //->add('prenom')

            // NOTE: Use form collection to allow multiple `played` forms per JoueurType
            ->add('played', CollectionType::class, [
                'entry_type' => PlayedType::class,
                'entry_options' => ['label' => false],
            ]);
    }

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

Controller :

$mainForm = $this->createForm(PlayedScoreType::class, $lastPartie);
$mainForm->handleRequest($request);

return $this->render('played/new.html.twig', [
    'formulaires' => $mainForm->createView(),
]);
1
You wouldn't want to do it that way I don't think - read up on embedded forms. - Alex.Barylski
Ok but is it possible to loop my formArray in the "embedded array" ? - Patrick Rey
Tournament is the main form in which you would embed the individual player forms - each player form will embed and render and the forms API will handle the persistence, etc. - Alex.Barylski
@Alex I don't really see how to do it. Do you have a more concrete example ? I edited my post with my database, maybe it's clearer - Patrick Rey

1 Answers

0
votes

https://symfony.com/doc/current/form/embedded.html

Embedding forms is as simple as defining two or more and when adding a form field to the outer/main form, one or more of it's fields/elements are nested forms:

class PlayedType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('max')
            ->add('score')
            ->add('points');
    }

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

class JoueurType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('nom')
            ->add('prenom')

            // NOTE: Use form collection to allow multiple `played` forms per JoueurType
            ->add('played', CollectionType::class, [
                'entry_type' => PlayedType::class,
                'entry_options' => ['label' => false],
            ]);
    }

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

class TournoiType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        //
        // NOTE: Use embeded form to connect the player with a tournement 1:1 -- otherwise use another form collection
        $builder
            ->add('date')
            ->add('disputed', JoueurType::class);
    }

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