symfony/ux-autocomplete
JavaScript-powered autocomplete for Symfony forms. Enhances select and entity fields with search-as-you-type suggestions, async loading, and a smooth UX. Part of Symfony UX; docs and issues live in the main symfony/ux repository.
composer require symfony/ux-autocomplete
npm install @symfony/ux-autocomplete
config/bundles.php:
return [
// ...
Symfony\UX\AutocompleteBundle\AutocompleteBundle::class => ['all' => true],
];
assets/app.js:
import './controllers/autocomplete_controller';
UserAutocompleteType):
use Symfony\UX\Autocomplete\Attribute\AsEntityAutocompleteField;
#[AsEntityAutocompleteField]
class UserAutocompleteType extends AbstractType {
public function configureOptions(OptionsResolver $resolver): void {
$resolver->setDefaults([
'class' => User::class,
'choice_label' => 'email', // Field to display
]);
}
}
config/routes/autocomplete.yaml):
autocomplete_user:
path: /api/user-autocomplete
controller: App\Controller\AutocompleteController::searchUsers
methods: GET
#[Route('/api/user-autocomplete', name: 'autocomplete_user')]
public function searchUsers(Request $request, EntityManagerInterface $em): Response {
return $this->json(
$this->getAutocompleteResults($request->query->get('query'), $em)
);
}
Replace a standard EntityType field with AsEntityAutocompleteField for a seamless search experience:
$builder->add('user', UserAutocompleteType::class, [
'label' => 'Search Users',
'min_characters' => 2, // Trigger search after 2 chars
'max_results' => 10, // Limit dropdown items
]);
AsEntityAutocompleteField for Doctrine entities.#[AsEntityAutocompleteField].findBy query).choice_label, choice_value, or getAttributes().#[AsEntityAutocompleteField]
class ProductAutocompleteType extends AbstractType {
public function configureOptions(OptionsResolver $resolver): void {
$resolver->setDefaults([
'class' => Product::class,
'choice_label' => 'name',
'choice_value' => 'id',
'get_attributes' => function (?Product $product) {
return ['data-price' => $product->getPrice()];
},
]);
}
}
AsAutocompleteField for non-entity data (e.g., API responses).#[AsAutocompleteField].tom_select_options for UI customization.#[AsAutocompleteField(route: 'api_search_products')]
class RemoteProductAutocompleteType extends AbstractType {
public function configureOptions(OptionsResolver $resolver): void {
$resolver->setDefaults([
'route' => 'api_search_products',
'tom_select_options' => [
'plugins' => ['remove_button'],
'placeholder' => 'Search products...',
],
]);
}
}
LiveComponent for dynamic forms.disabled or option changes trigger updates (works out-of-the-box since v2.8).reset_on_focus to clear stale data:
$resolver->setDefaults([
'reset_on_focus' => true,
]);
#[AsEntityAutocompleteField]
class DynamicUserAutocompleteType extends AbstractType {
public function configureOptions(OptionsResolver $resolver): void {
$resolver->setDefaults([
'class' => User::class,
'reset_on_focus' => true, // Critical for LiveComponents
]);
}
}
max_results + automatic pagination for large datasets.max_results (e.g., 10).Doctrine\ORM\QueryBuilder with setMaxResults).loading_more_text option for UX feedback:$resolver->setDefaults([
'max_results' => 10,
'tom_select_options' => [
'loading_more_text' => 'Loading more...',
],
]);
#[AsEntityAutocompleteField]
class CategoryAutocompleteType extends AbstractType {
public function configureOptions(OptionsResolver $resolver): void {
$resolver->setDefaults([
'class' => Category::class,
'get_attributes' => function (?Category $category) {
return ['data-color' => $category->getColor()];
},
'tom_select_options' => [
'option_group_field' => 'parent', // For nested categories
'option_group_label' => 'name',
],
]);
}
}
choice_loader for custom validation (e.g., LazyChoiceLoader).$resolver->setDefaults([
'options_as_html' => false, // Default (safe)
]);
$resolver->setDefaults([
'options_as_html' => true,
]);
Route Configuration:
Resources/routes.php to config/routes.php).ux_autocomplete route in config/routes/ux_autocomplete.yaml.PHP/Symfony Version Mismatch:
composer require symfony/ux-autocomplete:^2.35
Stimulus Controller Not Loaded:
autocomplete_controller.js isn’t imported.assets/app.js includes:
import './controllers/autocomplete_controller';
Case-Sensitive IDs:
choice_value to specify the exact field:
$resolver->setDefaults([
'choice_value' => 'uuid', // Instead of 'id'
]);
LiveComponent Stale Data:
reset_on_focus:
$resolver->setDefaults([
'reset_on_focus' => true,
]);
XSS Vulnerabilities:
options_as_html explicitly if needed:
$resolver->setDefaults([
'options_as_html' => true, // Only if intentional
]);
TomSelect Plugins Not Working:
clear_button) not applying.$resolver->setDefaults([
'tom_select_options' => [
'plugins' => [
'clear_button' => false,
],
],
]);
Network tab) to verify:
[{text: "...", value: 1}]).How can I help you explore Laravel packages today?