Skip to content

[Autocomplete] (using without form) How to pass extra_options to stimulus controller ? #2368

Open
@matthieumastadenis

Description

@matthieumastadenis

Hello,

I'm using the autocomplete component outside of a form and I need to use extra_options. I followed the documentation and implemented the following class:

<?php

namespace App\Autocompleter;

use App\Entity\Tag;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use Symfony\UX\Autocomplete\OptionsAwareEntityAutocompleterInterface;

#[AutoconfigureTag('ux.entity_autocompleter', [ 'alias' => 'tag' ])]
class TagAutocompleter implements OptionsAwareEntityAutocompleterInterface
{

    /**
     * @var array<string, mixed>
     */
    protected array $options = [];

    public function getEntityClass(): string
    {
        return Tag::class;
    }

    /**
     * @param array<string, mixed> $options
     */
    public function setOptions(array $options): void
    {
        $this->options = $options;
    }

    /**
     * @param EntityRepository<Tag> $repository
     */
    public function createFilteredQueryBuilder(
        EntityRepository $repository,
        string           $query,
    ): QueryBuilder {
        $extra   = $this->options['extra_options'] ?? [];
        $context = $extra['context'] ?? null;

        $qb = $repository->createQueryBuilder('t')
            ->andWhere('t.name LIKE :name')
            ->setParameter('name', '%'.$query.'%')
        ;

        if ($context !== null) {
            $qb->where('t.context=:context')
                ->setParameter('context', (string) $context)
            ;
        }

        return $qb;
    }

    /**
     * @throws \Exception
     */
    public function getLabel(object $entity): string
    {
        if (!($entity instanceof Tag)) {
            return throw new \Exception('Object of class '.($entity::class).' is not a Tag');
        }

        return $entity->getName();
    }

    /**
     * @throws \Exception
     */
    public function getValue(object $entity): string
    {
        if (!($entity instanceof Tag)) {
            return throw new \Exception('Object of class '.($entity::class).' is not a Tag');
        }

        return (string) $entity->getId();
    }

    public function isGranted(Security $security): bool
    {
        return true;
    }
}

However, I cannot find how to properly pass my extra_options to the stimulus controller from twig. Unless I'm mistaken, I think the "Manually using stimulus controller" section of the documentation lacks some precision about that.

I first tried this:

<select
    id="attachment_{{ id }}_tags"
    name="attachments[{{ id }}][tags]"
    multiple
    {{ stimulus_controller('symfony/ux-autocomplete/autocomplete', {
        url: path('ux_entity_autocomplete', { alias: 'tag', extra_options: { context: attachmentTagContext.value } }),
    }) }}
></select>

...which resulted in the following error:

Input value "extra_options" contains a non-scalar value.

Then I tried this (with a custom base64_encode filter):

<select
    id="attachment_{{ id }}_tags"
    name="attachments[{{ id }}][tags]"
    multiple
    {{ stimulus_controller('symfony/ux-autocomplete/autocomplete', {
        url: path('ux_entity_autocomplete', { alias: 'tag', extra_options: { context: attachmentTagContext.value }|json_encode|base64_encode }),
    }) }}
></select>

...which also gave me an error:

The extra options are missing the checksum.

So, how can I simply pass my extra options? Do I have to manually create and include the checksum myself (if so, how exactly please?) or is there a simpler way to achieve this?

Thanks

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions