Search code examples
formssymfonynestedembedeasyadmin

Custom nested form type easyadmin


I have an entity User and an entity Address which are in OneToOne relationship. I would like to display the address type in the User Crud in EasyAdmin, and I don't find a way to do just like Symfony ->add('address', AddressType::class). I tried the following options:

CollectionField::new('address')
            ->setEntryIsComplex(true)
            ->setEntryType(AddressType::class)
            ->setFormTypeOptions([
                'by_reference' => false,
                'required' => true
            ]),

But this makes the user able to add as many as addresses he wants, although I just want one.

AssociationField::new('address')->hideOnIndex()

This one makes the user choose an existing address in a list. That's not an embed of a form type.

Does anyone have an idea?


Solution

  • The solution I found is as follows:

    Create Address Field like this

    <?php
    
    namespace App\Field;
    
    use App\Form\AddressType;
    use EasyCorp\Bundle\EasyAdminBundle\Contracts\Field\FieldInterface;
    use EasyCorp\Bundle\EasyAdminBundle\Field\FieldTrait;
    
    final class AddressField implements FieldInterface
    {
        use FieldTrait;
    
        public static function new(string $propertyName, ?string $label = 'Address'): self
        {
            return (new self())
                ->setProperty($propertyName)
                ->setLabel($label)
                // this template is used in 'index' and 'detail' pages
                ->setTemplatePath('admin/field/address.html.twig')
                // this is used in 'edit' and 'new' pages to edit the field contents
                // you can use your own form types too
                ->setFormType(AddressType::class)
                ->addCssClass('field-address')
            ;
        }
    }
    

    And then use it in your User Crud Controller

    public function configureFields(string $pageName): iterable
    {
      // Other fields
    
      yield AddressField::new('address'); // Your new address field
    }
    

    templates/admin/field/address.html.twig template would be like this

    {% if field.value is defined %}  
      <dl class="row justify-content-center">
        <dt class="col-3 text-right">City</dt>
        <dd class="col-9">{{ field.value.city }}</dd>
        <dt class="col-3 text-right">Address 1</dt>
        <dd class="col-9">{{ field.value.address1 }}</dd>
        <dt class="col-3 text-right">Address 2</dt>
        dd class="col-9">{{ field.value.address2 }}</dd>
      </dl>
    {% endif %}