> For the complete documentation index, see [llms.txt](https://stack.sylius.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://stack.sylius.com/cookbook/admin_panel/using-autocompletes.md).

# Using autocompletes

The [SyliusBootstrapAdminUi](/bootstrap-admin-ui/getting-started.md) package uses[ Symfony UX ](https://ux.symfony.com/)under the hood. Thus, [UX autocomplete](https://symfony.com/bundles/ux-autocomplete/current/index.html) is already setup and configured in your admin panel. This means that any simple `ChoiceType` filter form can be turned into an autocomplete simply by setting `autocomplete` to `true` in form options.

```php
public function configureOptions(OptionsResolver $resolver): void
{
        $resolver->setDefaults([
            'choices' => $this->getChoices(),
            'placeholder' => 'sylius.ui.all',
            'autocomplete' => true,
        ]);
}

public function getParent(): string
{
    return ChoiceType::class;
}

```

However, if your autocomplete filter requires fetching data from another entity, you will need to use a `BaseEntityAutocompleteType` in order to fetch your options via AJAX.

All you need to start leveraging this functionality is a bit of routing config.

### Configure the entity autocomplete route

{% tabs %}
{% tab title="PHP" %}
{% code title="config/routes/ux\_autocomplete.php" %}

```php
<?php

declare(strict_types=1);

use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;

return static function (RoutingConfigurator $routingConfigurator): void {
    // ...
    $routingConfigurator
        ->add('ux_entity_autocomplete_admin', '/admin/autocomplete/{alias}')
        ->controller('ux.autocomplete.entity_autocomplete_controller')
    ;
};

```

{% endcode %}
{% endtab %}

{% tab title="YAML" %}
{% code title="config/routes/ux\_autocomplete.yaml" %}

```yaml
# ...
ux_entity_autocomplete_admin:
    path: '/admin/autocomplete/{alias}'
    controller: 'ux.autocomplete.entity_autocomplete_controller'
```

{% endcode %}
{% endtab %}
{% endtabs %}

This adds a new `ux_entity_autocomplete_admin` AJAX route dedicated to your autocompletes.

### Add a grid filter with entity autocomplete

First, you need to create an [entity autocomplete field ](https://symfony.com/bundles/ux-autocomplete/current/index.html#usage-in-a-form-with-ajax).

{% code title="src/Form/SpeakerAutocompleteType.php" lineNumbers="true" %}

```php
<?php

declare(strict_types=1);

namespace App\Form;

use App\Entity\Speaker;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\UX\Autocomplete\Form\AsEntityAutocompleteField;
use Symfony\UX\Autocomplete\Form\BaseEntityAutocompleteType;

#[AsEntityAutocompleteField(
    alias: 'app_admin_speaker',
    route: 'ux_entity_autocomplete_admin', // Use the route you just configured.
)]
final class SpeakerAutocompleteType extends AbstractType
{
    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'class' => Speaker::class,
            'choice_label' => 'fullName',
        ]);
    }

    public function getParent(): string
    {
        return BaseEntityAutocompleteType::class;
    }
}
```

{% endcode %}

Then, you need to create your custom grid filter.

{% tabs %}
{% tab title="AsFilter attribute - SyliusGridBundle v1.14+" %}
{% code title="src/Grid/Filter/SpeakerFilter.php" lineNumbers="true" %}

```php
<?php

declare(strict_types=1);

namespace App\Grid\Filter;

use App\Form\SpeakerAutocompleteType;
use Sylius\Component\Grid\Attribute\AsFilter;
use Sylius\Component\Grid\Data\DataSourceInterface;
use Sylius\Component\Grid\Filter\EntityFilter;
use Sylius\Component\Grid\Filtering\FilterInterface;

#[AsFilter(
    formType: SpeakerAutocompleteType::class,
    template: '@SyliusBootstrapAdminUi/shared/grid/filter/select.html.twig', // optional
)]
final class SpeakerFilter implements FilterInterface
{
    public function __construct(
        private readonly EntityFilter $entityFilter,
    ) {
    }

    public function apply(DataSourceInterface $dataSource, string $name, mixed $data, array $options): void
    {
        $this->entityFilter->apply($dataSource, $name, $data, $options);
    }
  }
```

{% endcode %}
{% endtab %}

{% tab title="SyliusGridBundle v1.13 (legacy)" %}
First, create your custom filter class.

{% code title="src/Grid/Filter/SpeakerFilter.php" lineNumbers="true" %}

```php
<?php

declare(strict_types=1);

namespace App\Grid\Filter;

use App\Form\SpeakerAutocompleteType;
use Sylius\Component\Grid\Data\DataSourceInterface;
use Sylius\Component\Grid\Filter\EntityFilter;
use Sylius\Component\Grid\Filtering\ConfigurableFilterInterface;

final class SpeakerFilter implements ConfigurableFilterInterface
{
    public function __construct(
        private readonly EntityFilter $entityFilter,
    ) {
    }

    public function apply(DataSourceInterface $dataSource, string $name, mixed $data, array $options): void
    {
        $this->entityFilter->apply($dataSource, $name, $data, $options);
    }

    public static function getFormType(): string
    {
        return SpeakerAutocompleteType::class;
    }

    public static function getType(): string
    {
        return self::class; // this will allow us to use FQCN instead of a string key.
    }
  
  }
```

{% endcode %}

Then, configure the Twig template this filter will use.

If you use PHP config files (which we recommend you do!), here is how you configure a filter template:

{% code title="config/packages/sylius\_grid.php" %}

```php
<?php

declare(strict_types=1);

use App\Grid\Filter\SpeakerFilter;
use App\Grid\Template\FilterTemplate;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
    $containerConfigurator->extension('sylius_grid', [
        'templates' => [
            'filter' => [
               SpeakerFilter::class => '@SyliusBootstrapAdminUi/shared/grid/filter/select.html.twig',
            ],
        ],
    ]);
};
```

{% endcode %}

Otherwise, if you're using YAML config files, here is the config for the filter template:

{% code title="config/packages/sylius\_grid.yaml" %}

```yaml
sylius_grid:
    # ...
    templates:
        filter:
            'App\Grid\Filter\SpeakerFilter': '@SyliusBootstrapAdminUi/shared/grid/filter/entity.html.twig'
```

{% endcode %}
{% endtab %}
{% endtabs %}

Now that the filter is configured, you can use it inside any grid.

{% code title="src/Grid/TalkGrid.php" lineNumbers="true" %}

```php
<?php

declare(strict_types=1);

namespace App\Grid;

use App\Grid\Filter\SpeakerFilter;
use Sylius\Bundle\GridBundle\Builder\Filter\Filter;
use Sylius\Bundle\GridBundle\Builder\GridBuilderInterface;
use Sylius\Bundle\GridBundle\Grid\AbstractGrid;
use Sylius\Bundle\GridBundle\Grid\ResourceAwareGridInterface;
use Sylius\Component\Grid\Attribute\AsGrid;

#[AsGrid(resourceClass: Talk::class)]
final class TalkGrid extends AbstractGrid
{
    // ...

    public function __invoke(GridBuilderInterface $gridBuilder): void
    {
        $gridBuilder
            // ...
            ->withFilters(
                Filter::create(name: 'speaker', type: SpeakerFilter::class)
                    ->setLabel('app.ui.speaker')
                    ->setOptions(['fields' => ['speakers.id']]),
            )
            // ...
        ;
    }
    
    // ...
}
```

{% endcode %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://stack.sylius.com/cookbook/admin_panel/using-autocompletes.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
