Reputation: 1879
I'm trying to generate a specific form.
I have two classes, City and Airport.
Every city got a few airport thanks to a OneToMany relationship.
When a user selects an airport, I would like to display only the ones that belong to a particular city. Is there a way to do so ?
So far, my form field looks like this :
->add('departure', 'entity', array(
'class' => 'AOFVHFlyBundle:Airport',
'property' => 'name',
'label' => 'Departure'
))
Upvotes: 0
Views: 124
Reputation: 6748
What you describe is (almost) exactly one of the documentation examples, I've adapted it for your need but I encourage you to read it.
Add an event listener on the PRE_SET_DATA
event to dynamically add the Airport
field, and a POST_SUBMIT
listener to the field that this new field depends on. If you add a POST_SUBMIT listener to a form child (e.g. sport), and add new children to the parent form, the Form component will detect the new field automatically and map it to the submitted client data.
YourGlobalEntityType.php
<?php
// src/AOFVHFlyBundle/Form/Type/YourGlobalEntityType.php
namespace AOFVHFlyBundle\Form\Type;
// ...
use Symfony\Component\Form\FormInterface;
use AOFVHFlyBundle\Entity\City;
use AOFVHFlyBundle\Entity\Airport;
class YourGlobalEntityType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('city', 'entity', array(
'class' => 'AOFVHFlyBundle:Airport',
'property' => 'name',
'label' => 'Departure'
))
;
$formModifier = function (FormInterface $form, City $city = null) {
$airports = null === $city ? array() : $city->getAvailableAirports();
$form->add('departure', 'entity', array(
'class' => 'AOFVHFlyBundle:Airport',
'property' => 'name',
'choices' => $airports,
'label' => 'Departure',
));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA,
function (FormEvent $event) use ($formModifier) {
// this would be your entity, i.e. YourGlobalEntity
$data = $event->getData();
$formModifier($event->getForm(), $data->getAirport());
}
);
$builder->get('city')->addEventListener(
FormEvents::POST_SUBMIT,
function (FormEvent $event) use ($formModifier) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$city = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $city);
}
);
}
// ...
}
Then in your Twig, add the javascript needed to make it dynamic:
{# src/AOFVHFlyBundle/Resources/views/YourGlobalEntity/create.html.twig #}
{{ form_start(form) }}
{{ form_row(form.city, { 'attr': { 'class':'yourglobalentity_city' } } ) }}
{{ form_row(form.departure, { 'attr': { 'class':'yourglobalentity_departure' } } ) }}
{# ... #}
{{ form_end(form) }}
<script>
var $city = $('.yourglobalentity_city');
// When city gets selected ...
$city.change(function() {
// ... retrieve the corresponding form.
var $form = $(this).closest('form');
// Simulate form data, but only include the selected city value.
var data = {};
data[$city.attr('name')] = $city.val();
// Submit data via AJAX to the form's action path.
$.ajax({
url : $form.attr('action'),
type: $form.attr('method'),
data : data,
success: function(html) {
// Replace current position field ...
$('.yourglobalentity_departure').replaceWith(
// ... with the returned one from the AJAX response.
$(html).find('.yourglobalentity_departure')
);
// Position field now displays the appropriate positions.
}
});
});
</script>
Upvotes: 1