ascensodigital/depend-select-bundle
Installation
Add the bundle to your composer.json:
composer require ascensodigital/depend-select-bundle
Enable the bundle in config/bundles.php:
return [
// ...
AscensoDigital\ADDependSelectBundle\AscensoDigitalDependSelectBundle::class => ['all' => true],
];
Basic Usage Register the type in your form builder:
use AscensoDigital\ADDependSelectBundle\Form\Type\DependSelectType;
$builder->add('fieldName', DependSelectType::class, [
'choices' => $choices, // Array of choices (e.g., ['id' => 'label'])
'depends_on' => 'parentField', // Field whose value triggers dependency
'ajax_url' => '/path/to/ajax-endpoint', // URL to fetch dependent choices
'placeholder' => 'Select an option...',
]);
First Use Case Create a cascading dropdown (e.g., country → state → city):
$builder->add('country', EntityType::class, ['class' => Country::class])
->add('state', DependSelectType::class, [
'depends_on' => 'country',
'ajax_url' => '/api/states-by-country',
]);
Frontend Integration
friendsofsymfony/jsrouting-bundle is configured for AJAX routes.{{ form_widget(form) }}
{{ form_rest(form) }}
<script src="{{ asset('bundles/dependselect/js/dependselect.js') }}"></script>
Backend Logic
StateController::getStatesByCountryAction):
public function getStatesByCountryAction(Request $request)
{
$countryId = $request->request->get('country_id');
$states = $this->stateRepository->findBy(['country_id' => $countryId]);
return $this->json(array_map(fn($s) => ['id' => $s->id, 'label' => $s->name], $states));
}
Dynamic Dependencies
$builder->add('country', EntityType::class)
->add('state', DependSelectType::class, [
'depends_on' => 'country',
'ajax_url' => '/api/states',
])
->add('city', DependSelectType::class, [
'depends_on' => 'state',
'ajax_url' => '/api/cities',
]);
Validation
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('parentField', ...)
->add('childField', DependSelectType::class, [
'depends_on' => 'parentField',
'constraints' => [new NotBlank()],
]);
}
AJAX Route Configuration
@Route or YamlRoute will break dependency loading.friendsofsymfony/jsrouting-bundle to generate JS routes:
# config/routing.yml
api_states:
path: /api/states
defaults: { _controller: App\Controller\StateController::getStatesAction }
methods: [GET]
CSRF Token Mismatch
CSRF token not found if the form is not properly configured.same-origin requests.Choice Format Mismatch
['id' => 'label'] format. Incorrect formats (e.g., objects) will break rendering.return $this->json(array_map(fn($item) => ['id' => $item->id, 'label' => $item->name], $items));
JavaScript Conflicts
dependselect.js is not loaded or conflicts with other JS (e.g., jQuery), dependencies won’t trigger.<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="{{ asset('bundles/dependselect/js/dependselect.js') }}"></script>
Check Network Requests
F12) → Network tab to verify AJAX calls to ajax_url are firing and returning valid JSON.Log AJAX Responses
$this->logger->debug('AJAX Request', ['data' => $request->request->all()]);
Inspect Form HTML
data-depends-on and data-ajax-url attributes are rendered:
<select data-depends-on="parentField" data-ajax-url="/api/endpoint">
Custom Templates
# templates/ADDependSelect/fields.html.twig
{% extends 'form_div_layout.html.twig' %}
{% block widget %}
<select {{ block('widget_attributes') }} data-depends-on="{{ depends_on }}" data-ajax-url="{{ ajax_url }}">
{% for choice in choices %}
<option value="{{ choice.id }}">{{ choice.label }}</option>
{% endfor %}
</select>
{% endblock %}
Dynamic Placeholders
$builder->add('state', DependSelectType::class, [
'placeholder' => 'Select state for {{ form.parentField.vars.data }}',
]);
Event Listeners
$form->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$form = $event->getForm();
$data = $event->getData();
if ($data->getParentField()) {
$form->add('childField', DependSelectType::class, [
'depends_on' => 'parentField',
'ajax_url' => '/api/dependent-choices',
]);
}
});
How can I help you explore Laravel packages today?