EasyCorp / EasyAdminBundle

EasyAdmin is a fast, beautiful and modern admin generator for Symfony applications.
MIT License
4.04k stars 1.02k forks source link

CrudAutocompleteType in CollectionField #4572

Open devcut opened 3 years ago

devcut commented 3 years ago

Symfony : 5.3.3 Easyadmin : 3.5.6

I try to create a CollectionField with autocomplete AssociationField.

CollectionField::new('promotionLines')
    ->setRequired(true)
    ->setEntryType(PromotionLineType::class)
;
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('product', CrudAutocompleteType::class, [
            'class' => Product::class,
        ])
}

But i have an empty field after each new lines.

devcut commented 3 years ago

Up

rodmar35 commented 2 years ago

Hi @devcut ! I have exactly the same problem... Did you manage to do it? If yes, how ?

thanks in advance

Martin1982 commented 2 years ago

I've being trying to achieve the same, but diving into the code I found out that autocomplete news a few extra options;

$builder->add('items', CollectionType::class, [
                    'label' => 'Interactions',
                    'allow_add' => true,
                    'allow_delete' => true,
                    'entry_type' => EntityType::class,
                    'entry_options' => [
                        'class' => SocialInteraction::class,
                        'label' => false,
                        'attr' => [
                            'data-ea-align' => 'left',
                            'data-ea-widget' => 'ea-autocomplete',
                            'data-ea-autocomplete-endpoint-url' => $this->getSearchEndpoint(),
                        ],
                    ],
                ]);

Adding the endpoint is achieved by using the AdminUrlGenerator and AdminContextProvider;

    public function __construct(AdminUrlGenerator $urlGenerator, AdminContextProvider $contextProvider)
    {
        $this->urlGenerator = $urlGenerator;
        $this->contextProvider = $contextProvider;
    }
    protected function getSearchEndPoint(): string
    {
        $context = $this->contextProvider->getContext();
        if (!$context) {
            throw new \RuntimeException('No context found');
        }
        $crud = $context->getCrud();
        if (!$crud)  {
            throw new \RuntimeException('No CRUD found');
        }
        $page = $crud->getCurrentPage();

        return $this->urlGenerator
            ->unsetAll()
            ->set('page', 1)
            ->setController(SocialInteractionCrudController::class)
            ->setAction('autocomplete')
            ->set(AssociationField::PARAM_AUTOCOMPLETE_CONTEXT, [
                EA::CRUD_CONTROLLER_FQCN => SocialInteractionCrudController::class,
                'propertyName' => 'interactionName',
                'originatingPage' => $page,
            ])
            ->generateUrl();
    }

With this setup I can add my autocomplete fields to the collection. But the rabbit hole goes deeper, once I add my second item every '1' in the HTML code gets replaced by '2', '3', '4', etc depending on the index of the item added. When researching this we found out that a piece of Javascript is responsible for this; https://github.com/EasyCorp/EasyAdminBundle/blob/23b5dc504bec41b1f71ab4728cc84bfcc864f5d1/assets/js/form-type-collection.js#L47

We haven't quite figured out why it replaces all of the HTML and how we could improve this, so if someone would like to help work on this that would be awesome. Probably we now have multiple issues;

I hope this helps to move things forward for everyone...

devcut commented 2 years ago

Maybe @javiereguiluz have a solution for that 🕺🏼

devcut commented 1 year ago

@javiereguiluz hello

ksn135 commented 1 year ago

So it worked for me. No problem with Javascript. Works fine on the current 4.x branch for Many-To-Many relation. Many thanks to @Martin1982 for his bit of code. I hope it comes in handy for someone else.

class DocSettingCrudController extends AbstractCrudController
{ 
    public function __construct(
        private AdminUrlGenerator $urlGenerator,
        private TranslatorInterface $translator,
    ) {
    }

    public static function getEntityFqcn(): string
    {
        return DocSetting::class;
    }

    protected function makeSearchEndPointForField(string $fieldName, string $crudControllerFqcn): string
    {
        return $this->urlGenerator
            ->unsetAll()
            ->set('page', 1)
            ->setController($crudControllerFqcn) 
            ->setAction('autocomplete')
            // The autocomplete context used to get custom closure with QB
            ->set(AssociationField::PARAM_AUTOCOMPLETE_CONTEXT, [
                EA::CRUD_CONTROLLER_FQCN => self::class,  // our controller
                'propertyName' => $fieldName, // our field
                'originatingPage' => $this->getContext()->getCrud()->getCurrentPage(), // current page
            ])
            ->generateUrl();
    }

    public function configureFields(string $pageName): iterable
    {
        return [
  ...
            Fields\CollectionField::new('conciliators', 'admin_label.common.field.conciliators')
                ->setEntryType(CrudAutocompleteType::class)
                ->setFormTypeOption('entry_options', [
                    'label' => false,
                    'class' => Employee::class,
                    'attr' => [
                        'data-ea-align' => 'left',
                        'data-ea-widget' => 'ea-autocomplete',
                        'data-ea-autocomplete-endpoint-url' => 
                            $this->makeSearchEndPointForField(
                                  'conciliators', 
                                  EmployeeCrudController::class
                            ),
                    ],
                ])
                ->setCustomOption(AssociationField::OPTION_QUERY_BUILDER_CALLABLE, 
                     function (QueryBuilder $qb): QueryBuilder {
                       // you can add custom condition here
                       return $qb;
                    }
                ),
...
        ];
    }

...
}

https://user-images.githubusercontent.com/230304/219220025-8439db57-79f8-4c11-b124-7042dc200baf.mov