Skip to content
Advertisement

Symfony 4: Use existing form type class in Sonata’s configureFormFields method

I know I can pull individual form elements from the type’s builder into the form mapper as described in the documentation:

You can add Symfony FormBuilderInterface instances to the FormMapper. This allows you to re-use a model form type. When adding a field using a FormBuilderInterface, the type is guessed.

Given you have a PostType like this:

use SymfonyComponentFormFormBuilderInterface;
use SymfonyBridgeDoctrineFormTypeEntityType;
use SymfonyComponentFormExtensionCoreTypeTextType;
use SymfonyComponentFormExtensionCoreTypeTextareaType;
use SymfonyComponentFormAbstractType;

class PostType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('author', EntityType::class, [
                'class' => User::class
            ])
            ->add('title', TextType::class)
            ->add('body', TextareaType::class)
        ;
    }
}

you can reuse it like this:

use SonataAdminBundleFormFormMapper;
use SonataAdminBundleAdminAbstractAdmin;
use AppFormPostType;

class Post extend AbstractAdmin
{
    protected function configureFormFields(FormMapper $formMapper)
    {
        $builder = $formMapper->getFormBuilder()->getFormFactory()->createBuilder(PostType::class);

        $formMapper
            ->with('Post')
                ->add($builder->get('title'))
                ->add($builder->get('body'))
            ->end()
            ->with('Author')
                ->add($builder->get('author'))
            ->end()
        ;
    }
}

However, this feels clunky if all you want is for Sonata to use that exact type as is.

I was therefore wondering if there is a shorthand that tells sonata to simply use the entire form type as is.

Something like:

protected function configureFormFields(FormMapper $formMapper)
{
    $formMapper->mapForm((new PostType()));
}

Advertisement

Answer

Maybe the shorter version using inherit_data might be what you are looking for.

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

From: How to inherit FormType in Sonata Admin?

With the Post example

use SonataAdminBundleFormFormMapper;
use SonataAdminBundleAdminAbstractAdmin;
use AppFormPostType;

class PostAdmin extend AbstractAdmin
{
    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
            ->add(
                'post',  // name does not seem to matter
                PostType::class, 
                [
                    'inherit_data' => true,
                ]
            );
    }
}

Using PostAdmin (and PostType) to map a child record in a 1:m relationship works too, but has problems with inline options and the table view does not seem to render it in separate columns as expected.

// Thread 1:m Post

/**
 * @ORMEntity
    ...
 */
class Thread
{
    protected $title = '';

    /**
     * @var Post[]|ArrayCollection
     *
     * @ORMOneToMany(...)
     */
    protected posts;
}
class Post extend AbstractAdmin
{
    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper->
            ->with('Thread')
            ->add('title')
            ->add(
                'posts',
                'sonata_type_collection',
                [
                    'label'        => 'Posts',
                    'required'     => false,
                    'by_reference' => false,
                ],
                [
                    'edit'     => 'inline', // does not seem to work
                    'inline'   => 'table',  // takes up one column in table
                    'multiple' => true,     // one row per entry
                ]
            );
    }
}

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement