Skip to content

Commit 7b5868b

Browse files
Update dynamic_form_modification.rst
Hi mates, The JavaScript parts use jQuery and, IMHO, it's not relevant. Also, performing an Ajax request is easier since fetch is available for JavaScript. That's why I propose this piece of code. Also, to use `form.getAttribute('action')` , you must manually define the URL called by the form. To do this, I give a third parameter to `createForm` and I set the action value in `SportMeetupType` with `$builder->setAction()` Yannick
1 parent 61d8041 commit 7b5868b

File tree

1 file changed

+41
-26
lines changed

1 file changed

+41
-26
lines changed

form/dynamic_form_modification.rst

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ The type would now look like::
447447
class SportMeetupType extends AbstractType
448448
{
449449
public function buildForm(FormBuilderInterface $builder, array $options): void
450-
{
450+
{
451451
$builder
452452
->add('sport', EntityType::class, [
453453
'class' => Sport::class,
@@ -487,6 +487,10 @@ The type would now look like::
487487
$formModifier($event->getForm()->getParent(), $sport);
488488
}
489489
);
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']);
490494
}
491495

492496
// ...
@@ -518,10 +522,11 @@ your application. Assume that you have a sport meetup creation controller::
518522

519523
class MeetupController extends AbstractController
520524
{
525+
#[Route('/create', name: 'app_meetup_create', methods: ['GET', 'POST'])]
521526
public function create(Request $request): Response
522527
{
523528
$meetup = new SportMeetup();
524-
$form = $this->createForm(SportMeetupType::class, $meetup);
529+
$form = $this->createForm(SportMeetupType::class, $meetup, ['action' => $this->generateUrl('app_meetup_create')]);
525530
$form->handleRequest($request);
526531
if ($form->isSubmitted() && $form->isValid()) {
527532
// ... save the meetup, redirect etc.
@@ -541,36 +546,46 @@ field according to the current selection in the ``sport`` field:
541546
.. code-block:: html+twig
542547

543548
{# templates/meetup/create.html.twig #}
544-
{{ form_start(form) }}
549+
{{ form_start(form, { 'attr' : { 'id' : 'supply_history_form' } }) }}
545550
{{ form_row(form.sport) }} {# <select id="meetup_sport" ... #}
546551
{{ form_row(form.position) }} {# <select id="meetup_position" ... #}
547552
{# ... #}
548553
{{ form_end(form) }}
549554

550555
<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));
574589
</script>
575590

576591
The major benefit of submitting the whole form to just extract the updated

0 commit comments

Comments
 (0)