Easyadminbundle: How to customize embedded form depending to parent form data ?

Created on 18 Mar 2017  路  5Comments  路  Source: EasyCorp/EasyAdminBundle

Hi Guys,

I'm trying to figure out how to customize embedded form for one my entity. This entity is linked to another by a oneToMany relation.

In easyAdmin I figured out how to embed my child form in the parent form thanks to :

...
edit:
    fields:
        - { property: 'client', type_options: { disabled: true } }
        - { property: 'user', type_options: { disabled: true } }
        - { property: 'ioConstraints', type: 'collection', type_options: { entry_type: 'AppBundle\Form\Type\IoConstraintType', by_reference: false } }

As you can see, my child entity is IoConstraint. It's basically described by a name and a value.
At this point I'm able to add/remove child occurrence directly within the parent form.

The thing is the name of an IoConstraint directly depend on the user property of the parent form.
It means that I need to access the parent form data so I can build a query_builder to define the possible value of my field.

So the question is : how can I can access the parent form data within the formType? Or is it even possible ?

Here is an example of what I tried to achieve in the child formType (I don't know how to define the userId)

<?php

namespace AppBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;

class IoConstraintType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array                $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $userId = "???????"; // Is defined in the parent form data

        $builder
            ->add('name', EntityType::class, array(
                'class' => 'AppBundle:Field',
                'query_builder' => function (EntityRepository $er) use ($userId) {
                    return $er->createQueryBuilder('f')
                        ->orderBy("f.name", "ASC")
                        ->where("f.user = {$userId}");
                },
                'choice_label' => 'name'
            ))
            ->add('value')
        ;
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\IoConstraint'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'appbundle_io_constraint';
    }
}

I also tried to work with the AdminController to override the createIoEntityFormBuilder method.
But as the formBuilder is already created when this code is reached, I'm not sure how I can override the query_builder for my IoConstraint name.

Hope all of this is clear !

Anyone can help ? :)

Btw : thanks for your great work !

Most helpful comment

But this solve a problem to create an other one : now that I've customize my InsertionOrder form builder to manage its child IoConstraint, I loose the easy_admin display configuration.

=> The embedded form IoConstraint is not displayed well as it now appears under the form actions.

I think that this is a know problem, but I don't know if there is an "easy" way to solve that.
Is overriding the edit view for that entity the solution I need ?

All 5 comments

An other way to achieve my goal would have been to set a custom form type for my parent entity, as suggested in this issue : https://github.com/javiereguiluz/EasyAdminBundle/issues/390

Doing this way would have allow me to pass the parameter (the userID) to the ioConstraint formType.

Ok so just to let you know I solve my problem overriding the create<Entity>FormBuilder() method and using FormEvent

Here is the admin controller code

public function createInsertionOrderEntityFormBuilder($entity, $view){

        // Get formBuilder to access its children ioConstraint to give it data
        $formBuilder = parent::createEntityFormBuilder($entity, $view);

        if($view == "edit" && $formBuilder->getData()->getUserForm()) {

            $user = $formBuilder->getData()->getUser();

            $formBuilder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($form) {

                /**
                 * An IoContraint associated to an IO directly depends on the "user" properties attached to the IO
                 * The IoConstraint "name" property should be a select list of all "Io->getUsers()->getName()"
                 * Data from the Io user must be given to its children form (the ioConstraint form)
                 * TO achieve that we use form event to inject the children formType with some data as parameters
                 */
                $event->getForm()->add('ioConstraints', CollectionType::class, [
                    'entry_type'    => IoConstraintType::class,
                    'allow_add'     => true,
                    'allow_delete'  => true,
                    'by_reference'  => false,
                    'entry_options' => [
                        'attr' => [
                            "user" => $user,
                        ]
                    ]
                ]);

            });
        }
        return $formBuilder;
    }

So in the IoConstraintType I'm now able to filter the available choice of a field.

But this solve a problem to create an other one : now that I've customize my InsertionOrder form builder to manage its child IoConstraint, I loose the easy_admin display configuration.

=> The embedded form IoConstraint is not displayed well as it now appears under the form actions.

I think that this is a know problem, but I don't know if there is an "easy" way to solve that.
Is overriding the edit view for that entity the solution I need ?

Same issue here, when i try to use a custom form type for a field in my entity, the entire form display is broken, all the fields appear under the form action, outside of their respective display groups.

I'm closing this issue because we're starting a new phase in the history of this bundle (see #2059). We've moved it into a new GitHub organization and we need to start from scratch: no past issues, no pending pull requests, etc.

I understand if you are angry or disappointed by this, but we really need to "reset" everything in order to reignite the development of this bundle.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  路  3Comments

ndench picture ndench  路  4Comments

Ealenn picture Ealenn  路  3Comments

lukasluecke picture lukasluecke  路  3Comments

liarco picture liarco  路  3Comments