简体   繁体   中英

Symfony2 create a form type to add multiple records of the same type

I need to create a form type that will create multiple records of a certain Entity.

I figured out to create a parent Form Type and then add a collection inside. This parent Type isn't bind to any entity, but child Type is. The problem is, that when I process the request, I get an empty data object.

Here is my parent Type:

class ChallengeCollectionType extends AbstractType {

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('email_invitations', CollectionType::class, [
            'entry_type' => EmailInvitationType::class
        ]);
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'csrf_protection'   => false
        ));
    }

}

My Child Type:

class EmailInvitationType extends AbstractType {

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('email', EmailType::class);
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class'        => Challenge::class,
            'csrf_protection'   => false
        ));
    }

}

Here is how I process my data in Controller:

public function inviteEmailAction(Request $request){

        $form = $this->createForm(ChallengeCollectionType::class);

        $form->handleRequest($request);

        dump($form->getData());
        dump($form->get('email_invitations')->getData());
        die();
}

I submit data in a POST request (this is API and there's no HTML form) like this:

challenge_collection[email_invitations][0][email] = "email@address.com"
challenge_collection[email_invitations][1][email] = "address@email.com"

And Controller returns empty [] for all dumps.

I've actually found a workaround, but it looks bad:

        $data = ['email_invitations' => [new Challenge(), new Challenge()]];        

        $form = $this->createForm(ChallengeCollectionType::class, $data);

        $form->handleRequest($request);

And this will work, so I have to send an array of empty objects of the type of the Entity to get request processed.

Or even this way:

    $data = ['email_invitations' => []];

    if(!empty($request->request->get('challenge_collection'))){
        if(!empty($request->request->get('challenge_collection')['email_invitations'])){
            for($i = 0; $i < count($request->request->get('challenge_collection')['email_invitations']); $i ++){
                $data['email_invitations'][] = new Challenge();
            }
        }
    }

There should be a better way to do it, please help me to find it.

You should try using allow_add and allow_delete options in collection field type. See the Collection field type documentation

Also, this is important for parent entity to have an mapped-by association with child entity, which would get you child objects in an ArrayCollection object in controller.

Further, if you want to save/remove them automatically as per the request, you need to implement a 'by_reference false and set association with cascade-persist and cascade-remove`.

I have used collection field type with API numerous times, and it worked like charm. Let me know if you need further explanation.

Maybe you should try in your controller something like :

$invitations = $this->getDoctrine()->getRepository('yourInvitationEntityClass')->findAll());         
$form = $this->createForm(ChallengeCollectionType::class, $invitations );

You could find explanations here :

http://symfony.com/doc/current/cookbook/form/form_collections.html

One form with all row of one entity

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM