@@ -447,7 +447,7 @@ The type would now look like::
447
447
class SportMeetupType extends AbstractType
448
448
{
449
449
public function buildForm(FormBuilderInterface $builder, array $options): void
450
- {
450
+ {
451
451
$builder
452
452
->add('sport', EntityType::class, [
453
453
'class' => Sport::class,
@@ -487,6 +487,10 @@ The type would now look like::
487
487
$formModifier($event->getForm()->getParent(), $sport);
488
488
}
489
489
);
490
+
491
+ // by default, action does not appear in the form tag
492
+ // you can set this value by passing the controller route
493
+ $builder->setAction($options['action']);
490
494
}
491
495
492
496
// ...
@@ -518,10 +522,11 @@ your application. Assume that you have a sport meetup creation controller::
518
522
519
523
class MeetupController extends AbstractController
520
524
{
525
+ #[Route('/create', name: 'app_meetup_create', methods: ['GET', 'POST'])]
521
526
public function create(Request $request): Response
522
527
{
523
528
$meetup = new SportMeetup();
524
- $form = $this->createForm(SportMeetupType::class, $meetup);
529
+ $form = $this->createForm(SportMeetupType::class, $meetup, ['action' => $this->generateUrl('app_meetup_create')] );
525
530
$form->handleRequest($request);
526
531
if ($form->isSubmitted() && $form->isValid()) {
527
532
// ... save the meetup, redirect etc.
@@ -541,36 +546,46 @@ field according to the current selection in the ``sport`` field:
541
546
.. code-block :: html+twig
542
547
543
548
{# templates/meetup/create.html.twig #}
544
- {{ form_start(form) }}
549
+ {{ form_start(form, { 'attr' : { 'id' : 'supply_history_form' } } ) }}
545
550
{{ form_row(form.sport) }} {# <select id="meetup_sport" ... #}
546
551
{{ form_row(form.position) }} {# <select id="meetup_position" ... #}
547
552
{# ... #}
548
553
{{ form_end(form) }}
549
554
550
555
<script>
551
- var $sport = $('#meetup_sport');
552
- // When sport gets selected ...
553
- $sport.change(function() {
554
- // ... retrieve the corresponding form.
555
- var $form = $(this).closest('form');
556
- // Simulate form data, but only include the selected sport value.
557
- var data = {};
558
- data[$sport.attr('name')] = $sport.val();
559
- // Submit data via AJAX to the form's action path.
560
- $.ajax({
561
- url : $form.attr('action'),
562
- type: $form.attr('method'),
563
- data : data,
564
- complete: function(html) {
565
- // Replace current position field ...
566
- $('#meetup_position').replaceWith(
567
- // ... with the returned one from the AJAX response.
568
- $(html.responseText).find('#meetup_position')
569
- );
570
- // Position field now displays the appropriate positions.
571
- }
572
- });
573
- });
556
+ const form = document.getElementById('sport_meetup_form');
557
+ const form_select_sport = document.getElementById('meetup_sport');
558
+ const form_select_position = document.getElementById('meetup_position');
559
+
560
+ const updateForm = async (data, url, method) => {
561
+ const req = await fetch(url, {
562
+ method: method,
563
+ body: data,
564
+ headers: {
565
+ 'Content-Type': 'application/x-www-form-urlencoded',
566
+ 'charset': 'utf-8'
567
+ }
568
+ });
569
+
570
+ const text = await req.text();
571
+ return text;
572
+ };
573
+
574
+ const parseTextToHtml = (text) => {
575
+ const parser = new DOMParser();
576
+ const html = parser.parseFromString(text, 'text/html');
577
+ return html;
578
+ };
579
+
580
+ const changeOptions = async (e) => {
581
+ const requestBody = e.target.getAttribute('name') + '=' + e.target.value;
582
+ const updateFormResponse = await updateForm(requestBody, form.getAttribute('action'), form.getAttribute('method'));
583
+ const html = parseTextToHtml(updateFormResponse);
584
+ const new_form_select_position = html.getElementById('meetup_position');
585
+ form_select_position.innerHTML = new_form_select_position.innerHTML;
586
+ };
587
+
588
+ form_select_sport.addEventListener('change', (e) => changeOptions(e));
574
589
</script>
575
590
576
591
The major benefit of submitting the whole form to just extract the updated
0 commit comments