### Install Symfony UX Autocomplete
Source: https://context7.com/symfony/ux-autocomplete/llms.txt
Use Composer to install the bundle and npm to manage the required JavaScript assets.
```bash
composer require symfony/ux-autocomplete
# If using WebpackEncore, install assets and restart Encore
npm install --force
npm run watch
```
--------------------------------
### Install Assets for WebpackEncore
Source: https://github.com/symfony/ux-autocomplete/blob/3.x/doc/index.rst
Install necessary JavaScript assets and restart the build process when using WebpackEncore.
```terminal
$ npm install --force
$ npm run watch
```
--------------------------------
### Install Symfony UX Autocomplete
Source: https://github.com/symfony/ux-autocomplete/blob/3.x/doc/index.rst
Use Composer to add the bundle to your Symfony project.
```terminal
$ composer require symfony/ux-autocomplete
```
--------------------------------
### Install Symfony UX Autocomplete dependencies
Source: https://github.com/symfony/ux-autocomplete/blob/3.x/assets/README.md
Commands to install the required PHP package and the corresponding npm package version.
```shell
composer require symfony/ux-autocomplete:2.23.0
npm add @symfony/ux-autocomplete@2.23.0
```
--------------------------------
### Configure TextType Field with Autocomplete and Tom Select Options
Source: https://github.com/symfony/ux-autocomplete/blob/3.x/doc/index.rst
This example shows how to configure a `TextType` field with autocomplete enabled and specific `tom_select_options` for creating new items.
```php
$builder
// ...
->add('tags', TextType::class, [
'autocomplete' => true,
'tom_select_options' => [
'create' => true,
'createOnBlur' => true,
'delimiter' => ',',
],
// 'autocomplete_url' => '... optional: custom endpoint, see below',
])
;
```
--------------------------------
### Pass Extra Options to FoodAutocompleteField
Source: https://github.com/symfony/ux-autocomplete/blob/3.x/doc/index.rst
This example demonstrates passing `excluded_foods` as an extra option to the `FoodAutocompleteField` to dynamically filter results.
```php
// src/Form/FoodForm.php
// ...
class FoodForm extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$currentFoodId = $builder->getData()->getId();
$builder
->add('food', FoodAutocompleteField::class, [
'extra_options' => [
'excluded_foods' => [$currentFoodId],
],
)
;
}
}
```
--------------------------------
### Implement EntityAutocompleterInterface
Source: https://github.com/symfony/ux-autocomplete/blob/3.x/doc/index.rst
Create a class that implements EntityAutocompleterInterface and tag it with 'ux.entity_autocompleter' to expose an autocompleter endpoint. The 'alias' option is used in the route.
```php
namespace App\Autocompleter;
use App\Entity\Food;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
use Symfony\UX\Autocomplete\EntityAutocompleterInterface;
#[AutoconfigureTag('ux.entity_autocompleter', ['alias' => 'food'])]
class FoodAutocompleter implements EntityAutocompleterInterface
{
public function getEntityClass(): string
{
return Food::class;
}
public function createFilteredQueryBuilder(EntityRepository $repository, string $query): QueryBuilder
{
return $repository
// the alias "food" can be anything
->createQueryBuilder('food')
->andWhere('food.name LIKE :search OR food.description LIKE :search')
->setParameter('search', '%'.$query.'%')
// maybe do some custom filtering in all cases
//->andWhere('food.isHealthy = :isHealthy')
//->setParameter('isHealthy', true)
;
}
public function getLabel(object $entity): string
{
return $entity->getName();
}
public function getValue(object $entity): string
{
return $entity->getId();
}
public function isGranted(Security $security): bool
{
// see the "security" option for details
return true;
}
}
```
--------------------------------
### Configure Tom Select CSS in assets/controllers.json
Source: https://github.com/symfony/ux-autocomplete/blob/3.x/doc/index.rst
Set CSS files for Tom Select styling. Use 'tom-select.bootstrap5.css' for Bootstrap 5 compatibility.
```json
"autoimport": {
"tom-select/dist/css/tom-select.default.css": false,
"tom-select/dist/css/tom-select.bootstrap5.css": true
}
```
--------------------------------
### Create a Custom Autocompleter (Without Form)
Source: https://context7.com/symfony/ux-autocomplete/llms.txt
Implement `EntityAutocompleterInterface` to create a standalone autocomplete API endpoint. This is useful for manual Stimulus controller initialization.
```php
'product'])]
class ProductAutocompleter implements EntityAutocompleterInterface
{
public function getEntityClass(): string
{
return Product::class;
}
public function createFilteredQueryBuilder(EntityRepository $repository, string $query): QueryBuilder
{
$qb = $repository->createQueryBuilder('p')
->andWhere('p.isEnabled = :enabled')
->setParameter('enabled', true);
if ($query) {
$qb->andWhere('p.name LIKE :search OR p.sku LIKE :search')
->setParameter('search', '%' . $query . '%');
}
return $qb->setMaxResults(20);
}
public function getLabel(object $entity): string
{
return sprintf('%s (SKU: %s)', $entity->getName(), $entity->getSku());
}
public function getValue(object $entity): mixed
{
return $entity->getId();
}
public function getAttributes(object $entity): array
{
return [
'data-price' => $entity->getPrice(),
'data-category' => $entity->getCategory()?->getName(),
];
}
public function isGranted(Security $security): bool
{
return $security->isGranted('ROLE_USER');
}
public function getGroupBy(): mixed
{
// Group by category
return 'category.name';
}
}
// Usage in Twig template:
//
```
--------------------------------
### Extend Tom Select with Stimulus
Source: https://github.com/symfony/ux-autocomplete/blob/3.x/doc/index.rst
Create a custom Stimulus controller to listen for pre-connect and connect events, allowing modification of Tom Select options or access to the instance.
```javascript
// assets/controllers/custom-autocomplete_controller.js
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
initialize() {
this._onPreConnect = this._onPreConnect.bind(this);
this._onConnect = this._onConnect.bind(this);
}
connect() {
this.element.addEventListener('autocomplete:pre-connect', this._onPreConnect);
this.element.addEventListener('autocomplete:connect', this._onConnect);
}
disconnect() {
// You should always remove listeners when the controller is disconnected to avoid side-effects
this.element.removeEventListener('autocomplete:connect', this._onConnect);
this.element.removeEventListener('autocomplete:pre-connect', this._onPreConnect);
}
_onPreConnect(event) {
// TomSelect has not been initialized - options can be changed
console.log(event.detail.options); // Options that will be used to initialize TomSelect
event.detail.options.onChange = (value) => {
// ...
};
}
_onConnect(event) {
// TomSelect has just been initialized and you can access details from the event
console.log(event.detail.tomSelect); // TomSelect instance
console.log(event.detail.options); // Options used to initialize TomSelect
}
}
```
--------------------------------
### Configure Tom Select Plugins
Source: https://github.com/symfony/ux-autocomplete/blob/3.x/doc/index.rst
Use the tom_select_options array to enable or disable specific Tom Select plugins within the OptionsResolver.
```php
$resolver->setDefaults([
'class' => Ingredient::class,
'tom_select_options' => [
'plugins' => [
// Enable Input Autogrow plugin
'input_autogrow',
// Enable Dropdown Header plugin, with custom configuration
'dropdown_header' => [
'title' => 'Select an ingredient',
],
// Force natively-enabled plugins (by UX Autocomplete) to be disabled
'clear_button' => false,
'remove_button' => false,
],
],
]);
```
--------------------------------
### Implement Options-Aware Autocompleter
Source: https://context7.com/symfony/ux-autocomplete/llms.txt
Implement `OptionsAwareEntityAutocompleterInterface` to receive extra options from the frontend. This enables dynamic filtering based on form context or other passed data.
```php
'dynamic_product'])]
class DynamicProductAutocompleter implements OptionsAwareEntityAutocompleterInterface
{
/** @var array */
private array $options = [];
public function getEntityClass(): string
{
return Product::class;
}
public function setOptions(array $options): void
{
$this->options = $options;
}
public function createFilteredQueryBuilder(EntityRepository $repository, string $query): QueryBuilder
{
$qb = $repository->createQueryBuilder('p');
// Access extra_options passed from the frontend
$categoryId = $this->options['extra_options']['category_id'] ?? null;
$excludeIds = $this->options['extra_options']['exclude_ids'] ?? [];
if ($categoryId) {
$qb->andWhere('p.category = :category')
->setParameter('category', $categoryId);
}
if (!empty($excludeIds)) {
$qb->andWhere($qb->expr()->notIn('p.id', $excludeIds));
}
if ($query) {
$qb->andWhere('p.name LIKE :search')
->setParameter('search', '%' . $query . '%');
}
return $qb;
}
public function getLabel(object $entity): string
{
return $entity->getName();
}
public function getValue(object $entity): mixed
{
return $entity->getId();
}
public function getAttributes(object $entity): array
{
return [];
}
public function isGranted(Security $security): bool
{
return true;
}
public function getGroupBy(): mixed
{
return null;
}
}
```
--------------------------------
### Configure Tom Select Options in EntityType
Source: https://context7.com/symfony/ux-autocomplete/llms.txt
Customize Tom Select behavior by passing options through `tom_select_options` in the EntityType configuration. This allows for enabling plugins, setting limits, and controlling selection behavior.
```php
add('ingredients', EntityType::class, [
'class' => Ingredient::class,
'multiple' => true,
'autocomplete' => true,
'tom_select_options' => [
// Enable plugins
'plugins' => [
'input_autogrow',
'dropdown_header' => [
'title' => 'Select ingredients',
],
// Disable default plugins
'clear_button' => false,
'remove_button' => false,
],
// Other Tom Select options
'maxItems' => 5,
'hideSelected' => true,
'closeAfterSelect' => false,
],
])
// TextType with tag-like input
->add('tags', TextType::class, [
'autocomplete' => true,
'tom_select_options' => [
'create' => true,
'createOnBlur' => true,
'delimiter' => ',',
],
]);
}
}
```
--------------------------------
### Configure Stimulus Controller with URL
Source: https://github.com/symfony/ux-autocomplete/blob/3.x/doc/index.rst
Pass a 'url' value to the Stimulus controller to enable Ajax autocompletion. This works well with custom autocompleters.
```html+twig