Smart Form Controls

Ajax-Powered Autocomplete <select>

Breathe life into EntityType and ChoiceType fields with Tom Select and a sprinkle of Ajax.

composer require symfony/ux-autocomplete

What Autocomplete gives you

  • Search as you type

    Query the server without leaving the form.

  • A real form type

    Drop it into any Symfony form.

  • Doctrine aware

    Point it at an entity and it queries for you.

  • Create on the fly

    Let users add a value that does not exist yet.

  • Multiple selection

    Tags, grouping and dependent fields.

Ajax-powered Form Select

Add Autocomplete to your app.

Ajax-powered, auto-completable select elements

src/Form/TimeForAMealForm.php
// ... use statements hidden - click to show
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;

/**
 * @extends AbstractType<array<string, mixed>>
 */
class TimeForAMealForm extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('foods', FoodAutocompleteField::class)
            ->add('name', TextType::class, [
                'label' => 'What should we call this meal?',
            ])
        ;
    }
}
// ... use statements hidden - click to show
use App\Entity\Food;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\Count;
use Symfony\UX\Autocomplete\Form\AsEntityAutocompleteField;
use Symfony\UX\Autocomplete\Form\BaseEntityAutocompleteType;

/**
 * @extends AbstractType<Collection<int, Food>>
 */
#[AsEntityAutocompleteField]
class FoodAutocompleteField extends AbstractType
{
    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'class' => Food::class,
            'searchable_fields' => ['name'],
            'label' => 'What sounds tasty?',
            'choice_label' => 'name',
            'multiple' => true,
            'constraints' => [
                new Count(min: 1, minMessage: 'We need to eat *something*'),
            ],
            // 'security' => 'ROLE_SOMETHING',
        ]);
    }

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

UX Autocomplete

From a select to a search field

Where the options come from.

A plain select ships every row to the browser. Autocomplete keeps them on the server and fetches only what the visitor is looking for.

One option to switch it on

Add autocomplete to an existing EntityType or ChoiceType and the field becomes searchable.

$builder->add('food', EntityType::class, [
    'class' => Food::class,
    'autocomplete' => true,
]);

Its own endpoint

The attribute registers a dedicated controller, so the browser queries the database instead of downloading it.

#[AsEntityAutocompleteField]
class FoodField extends AbstractType
{
    public function configureOptions(
        OptionsResolver $resolver,
    ): void {
        $resolver->setDefaults([
            'class' => Food::class,
        ]);
    }
}

Values that do not exist yet

allow_options_create lets a visitor type something new. Your code decides whether to persist it.

$resolver->setDefaults([
    'class' => Food::class,
    'allow_options_create' => true,
]);

Install Autocomplete.

$ composer require symfony/ux-autocomplete

More from Symfony UX.

Autocomplete is one package among many. They share the same Stimulus foundation and install the same way.

Image for the Map UX package

Map

Render interactive Maps in PHP with Leaflet or Google Maps.

Image for the Twig Components UX package

Twig Components

Create PHP classes that can render themselves

Image for the Live Components UX package

Live Components

Build dynamic interfaces with zero JavaScript

Browse every package

Keep Autocomplete at hand.

Documentation, the people behind it, and where to ask when something does not behave.