Corentoulf
Corentoulf

Reputation: 15

Validation of AJAX submitted forms in Symfony 5

I'm building an Address form in Symfony 5.1.

It is created in an AddressType Class that has some required fields.

$builder
        ->add('name', TextType::class, [
            'required' => false,
            'label'  => 'address.name',
            'help' => 'address.name_help',
            'attr' => [
                'placeholder' => 'address.name_ph',
            ]
        ])
        ->add('company', TextType::class, [
            'required' => false,
            'label'  => 'address.company',
            'attr' => [
                'placeholder' => 'address.company_ph',
            ]
        ])
        ->add('first_line', TextType::class, [
            'label'  => 'address.first_line',
            'attr' => [
                'placeholder' => 'address.first_line_ph',
            ]
        ])
        ->add('second_line', TextType::class, [
            'required' => false,
            'label'  => 'address.second_line',
            'attr' => [
                'placeholder' => 'address.second_line_ph',
            ]
        ])
        ->add('add_info', TextType::class, [
            'required' => false,
            'label'  => 'address.add_info',
            'help' => 'address.add_info_help',
            'attr' => [
                'placeholder' => 'address.add_info_ph',
            ]
        ])
        ->add('postcode', TextType::class, [
            'label'  => 'address.postcode',
            'attr' => [
                'placeholder' => 'address.postcode_ph',
            ]
        ])
        ->add('city', TextType::class, [
            'label'  => 'address.city',
            'attr' => [
                'placeholder' => 'address.city_ph',
            ]
        ])
        ->add('state', TextType::class, [
            'required' => false,
            'label'  => 'address.state',
            'attr' => [
                'placeholder' => 'address.state_ph',
            ]
        ])
        ->add('country', CountryType::class, [
            'label'  => 'address.country',
            'preferred_choices' => ['FR'],
            'attr' => [
                'data-toggle' => 'select',
                'placeholder' => 'address.country_ph',
            ]
        ])
        ->add('save',
                SubmitType::class,
                [
                    'label'  => $options['submit_btn_label'],
                ]
            );

If I submit this form with the submit button, everything works as expected, my form is being processed for validation and if It detects some errors, they are shown on each field.

Here is the function that handle the form :

public function new(Request $request)
{
    $user = $this->getUser();
    $address = new Address();
    $address->setCreatedBy($user);
    $form = $this->createForm(AddressType::class, $address);
    //handle form
    $form->handleRequest($request);
    if ($form->isSubmitted()){
        //if submit, add hidden fields
        $address = $form->getData();
        //if valid, process
        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($address);
            $em->flush();   

            $this->addFlash(
                'success',
                'Your address was created.'
            );
            return $this->redirectToRoute('address_index');
        }
    } 
    return $this->render('address/new.html.twig', [
        'form' => $form->createView(),
        'mode' => 'new',
    ]);          
}

Now, If I submit this form through an AJAX request :

$(document).on('click', '.create-address', function() {
    console.log('submitting new address form...');
    var $form = $(this).closest('form')
    var data = $form.serializeArray();
    $.ajax({
        url : $form.attr('action'),
        type: $form.attr('method'),
        data : data
    });
});

In this case, my form is processed for validation and It passes ($form->isValid() returns true) even if I don't provide some of the required fields.
This causes the process of persisting the object to occur and so I get a PDOException.

My question is:
Why is my form not handled the same way (especially at the validation step) according how I post the data ?
And how different are those two methods from the point of view of the function that handle the request ?

Upvotes: 0

Views: 1300

Answers (1)

msg
msg

Reputation: 8181

The required option only adds the required attribute to the markup. This forces the browser to provide a value, but doesn't add any validation server side. You can trigger validation before your ajax call and submit only if the form status is valid.

But it is recommended to add server side validation explicitly by using the constraints option in the form or annotating the target entity. Refer to the documentation for more details.

Upvotes: 2

Related Questions