EasyCorp / EasyAdminBundle

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

Error EntryCrudForm with Association nested in Collection #5287

Closed Luukkkiiii closed 1 year ago

Luukkkiiii commented 2 years ago

Describe the bug I wanted to get a CollectionField where i can insert Associations via the the new useEntryCrudForm(). When start typing inside the Association Field i got this Error:

Call to a member function getCustomOption() on null

To Reproduce EasyAdmin Version 4.3.0

Create Entitys (Inventory, InventorySet and Set) with OneToMany Relation from Inventory and Set to InventorySet (In my Case this i needed for a specific quantity).

Insert in SetCrudController CollectionField to inventorySets with ->useEntryCrudForm(InventorySetCrudController::class)

Insert in InventorySetCrudController AssociationField to Inventory with ->autocomplete()

Start Typing in the AssociationField inside the Collection

(OPTIONAL) Additional context error

htuscher commented 2 years ago

I had the same issue. Figured out it is due to the AssociationConfigurator which determines the $autocompleteContext controller by the request crud controller, not the crud controller of the actual nested entity. I fixed it by overriding the autocomplete function and specifying the CrudController manually:

public function autocomplete(AdminContext $context): JsonResponse
    {
        $queryBuilder = $this->createIndexQueryBuilder(
            $context->getSearch(),
            $context->getEntity(),
            FieldCollection::new([]),
            FilterCollection::new()
        );

        $autocompleteContext = $context->getRequest()->get(AssociationField::PARAM_AUTOCOMPLETE_CONTEXT);

        /** @var CrudControllerInterface $controller */
        $controller = $this->container
            ->get(ControllerFactory::class)
            ->getCrudControllerInstance(
                IncidentCrudController::class, // fix due to nested entity
                Action::INDEX,
                $context->getRequest()
            );
        /** @var FieldDto $field */
        $field = FieldCollection::new($controller->configureFields($autocompleteContext['originatingPage']))
            ->getByProperty($autocompleteContext['propertyName']);
        /** @var \Closure|null $queryBuilderCallable */
        $queryBuilderCallable = $field->getCustomOption(AssociationField::OPTION_QUERY_BUILDER_CALLABLE);

        if (null !== $queryBuilderCallable) {
            $queryBuilderCallable($queryBuilder);
        }

        $paginator = $this->container->get(PaginatorFactory::class)->create($queryBuilder);

        return JsonResponse::fromJsonString($paginator->getResultsAsJson());
    }
maciekjaros commented 1 year ago

@hhoechtl thanks a lot for this hint.

This solved my autocomplete problem. Without it, I was able to use CollectionField with my own EntryType. But I wasn't able to achieve ajax autocomplete there. The one built in easy admin, nor ux-autocomplete. Only the method with a dedicated crud controller and your fix worked.

JSmythSSG commented 1 year ago
public function autocomplete(AdminContext $context): JsonResponse

Can you give an example of what the working files looks like please? I've stuck the autocomplete in my the controller that is looking up the autocomplete but it doesnt seem to be overiding it

debuggerone commented 1 year ago

I FOUND YOU!

You are the guy who always puts 4 spaces in front of opening brackets after a newline.

Are you aware that you made alot of people very angry?

Angry enough to write code formatters and and even PSR for code styling.