Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork5.3k
Explained a more simple method of dynamic form handling available since #8827#2927
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -403,31 +403,33 @@ possible choices will depend on each sport. Football will have attack, defense, | ||
| goalkeeper etc... Baseball will have a pitcher but will not have goalkeeper. You | ||
| will need the correct options to be set in order for validation to pass. | ||
| The meetup is passed as an entity field to the form. So we can access each | ||
| sport like this:: | ||
| // src/Acme/DemoBundle/Form/Type/SportMeetupType.php | ||
| namespace Acme\DemoBundle\Form\Type; | ||
| // ... | ||
| class SportMeetupType extends AbstractType | ||
| { | ||
| public function buildForm(FormBuilderInterface $builder, array $options) | ||
| { | ||
| $builder | ||
| ->add('sport', 'entity', array(...)) | ||
| ; | ||
| $builder->addEventListener( | ||
| FormEvents::PRE_SET_DATA, | ||
| function(FormEvent $event) { | ||
| $form = $event->getForm(); | ||
| // this would be your entity, i.e. SportMeetup | ||
| $data = $event->getData(); | ||
| $positions = $data->getSport()->getAvailablePositions(); | ||
| $form->add('position', 'entity', array('choices' => $positions)); | ||
| } | ||
| ); | ||
| } | ||
| @@ -448,173 +450,69 @@ On a form, we can usually listen to the following events: | ||
| * ``BIND`` | ||
| * ``POST_BIND`` | ||
| .. versionadded:: 2.2.6 | ||
| The key is to add a ``POST_BIND`` listener to the field your new field is dependent | ||
| on. If you add a POST_BIND listener to a form child, and add new children to the parent | ||
| from there, the Form component will detect the new field automatically and maps it | ||
| to the client data if it is available. | ||
| The type would now look like:: | ||
| // src/Acme/DemoBundle/Form/Type/SportMeetupType.php | ||
| namespace Acme\DemoBundle\Form\Type; | ||
| // ... | ||
| Acme\DemoBundle\Entity\Sport; | ||
| Symfony\Component\Form\FormInterface; | ||
| class SportMeetupType extends AbstractType | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. missing namespace declarations and use statements. ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. I see now that the doc pages are quite inconsistent on this. In this specific page it even changes per example. What exactly is the standard on this? If I look at this page:http://symfony.com/doc/current/cookbook/form/direct_submit.html, I see that the namespace declaration is always there, but the use statements are simply replaced by http://symfony.com/doc/current/contributing/documentation/standards.html doesn't say anything about it Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Most of the times, we show all use statements in the first example on a page and fold it on the next examples in the same article. Only new use statements are shown after | ||
| { | ||
| public function buildForm(FormBuilderInterface $builder, array $options) | ||
| { | ||
| $builder | ||
| ->add('sport', 'entity', array(...)) | ||
| ; | ||
| $formModifier = function(FormInterface $form, Sport $sport) { | ||
| $positions = $data->getSport()->getAvailablePositions(); | ||
| $form->add('position', 'entity', array('choices' => $positions)); | ||
| } | ||
| $builder->addEventListener( | ||
| FormEvents::PRE_SET_DATA, | ||
| function(FormEvent $event) { | ||
| $form = $event->getForm(); | ||
| //this would be your entity, i.e. SportMeetup | ||
| $data = $event->getData(); | ||
| $formModifier($event->getForm(), $sport); | ||
| } | ||
| ); | ||
| $builder->get('meetup')->addEventListener( | ||
| FormEvents::POST_BIND, | ||
| function(FormEvent $event) use ($formModifier) { | ||
| // It's important here to fetch $event->getForm()->getData(), as | ||
| // $event->getData() will get you the client data (this is, the ID) | ||
| $sport = $event->getForm()->getData(); | ||
| $positions = $sport->getAvailablePositions(); | ||
| // 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(), $sport); | ||
| } | ||
| ); | ||
| } | ||
| } | ||
| You can see that you need to listen on these two events and have different callbacks | ||
| only because in two different scenarios, the data that you can use is available in different events. | ||
| Other than that, the listeners always perform exactly the same things on a given form. | ||
| One piece that may still be missing is the client-side updating of your form | ||
| after the sport is selected. This should be handled by making an AJAX call | ||