Disable form type checking if checked in Symfony

I am trying to create an address form with the payment and delivery address. When the checkbox on the delivery address is checked, I want to skip checking the form from this address.

I created the form type below using the toggle option, which will display and process the checkbox, however the form is still validated even when validated.

Symfony has documentation on how to implement this form , and even if I have almost the same code, validation does not turn off during validation. I do not use validation groups, so I simply disable the default group to disable entity validation.

AddressType builds the form for the Address class (which has annotation restrictions for some fields, such as NotBlank and Callback ).

 class AddressType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { if ($options["toggle"]) { $builder->add("toggle", CheckboxType::class, [ "mapped" => false, "required" => false, "label" => $options["toggle"] ]); } $builder ->add("name", TextType::class, [ "required" => !$options["toggle"] ]) ->add("address", TextType::class, [ "required" => !$options["toggle"] ]) ->add("zipcode", TextType::class, [ "label" => "Postcode", "required" => !$options["toggle"] ]) ->add("city", TextType::class, [ "required" => !$options["toggle"] ]) ->add("countryCode", ChoiceType::class, [ "choices" => Address::COUNTRY_CODES ]); } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ "toggle" => false, "data_class" => Address::class, "validation_groups" => function(FormInterface $form) { if ($form->has("toggle") && $form->get("toggle")->getData() === true) { return []; } return ["Default"]; } ]); $resolver->setAllowedTypes("toggle", ["bool", "string"]); } } 

I use this type:

 $addressForm = $this ->createFormBuilder([ "paymentAddress" => $paymentAddress, "shippingAddress" => $shippingAddress ]) ->add("paymentAddress", AddressType::class, [ "label" => false ]) ->add("shippingAddress", AddressType::class, [ "label" => false, "toggle" => "Use payment address" ]) ->add("submit", SubmitType::class, [ ]) ->getForm(); 

I iterate over this after a few hours, but I cannot understand why validation is not disabled, and I do not want to mask the shape over this small detail.

Why is checking for AddressType not disabled by closing in configureOptions? If this is not the case, how does it work, what would be the best solution to partially disable the check in order?

EDIT: even if when setting "validation_groups" => false in the default settings, in child elements created in the builder, or when using the form, validation will continue. This is not due to closure. Every online resource, including its own Symfony resource, claims that it should work, although ...

+5
source share
1 answer

[...], so I just disable the default group to disable entity checking.

Assuming the properties and restrictions of Address are as follows:

 /** * @Assert\NotBlank() */ private $name; // etc. 

"Validator" assumes that these properties will be evaluated using the Default group, because it always considers validation_groups empty (for example, return []; ) as ['Default'] (therefore, verification does not turn off during verification):

https://symfony.com/doc/current/validation/groups.html : If no groups are specified, all restrictions related to the Default group will be applied.

Solution to partially disable validation

If there are many ways to achieve it, but I will show you two of them:

  • If no data_class is set in the root form, then the Form group is available for checking this level:

     $addressForm = $this ->createFormBuilder([...], [ 'validation_groups' => 'Form', // <--- set ]) 

    Then, in configureOptions , set the Address group to default and Form , if the "toggle" checkbox is checked, also adds a Valid() constraint to check the cascade:

     public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ // ... "validation_groups" => function(FormInterface $form) { if ($form->has("toggle") && $form->get("toggle")->getData() === true) { return ['Form']; // <--- set } return ['Address']; // <--- set }, 'constraints' => [new Assert\Valid()], // <--- set ]); } 

    This means that when sending with disconnection: Form and Address groups are applied to the address fields, otherwise only the Form group is applied.

  • (Another way) In the Address class, add the group "Required" to all restrictions, it avoids checking these properties using the Default group:

     /** * @Assert\NotBlank(groups={"Required"}) // <--- set */ private $name; // etc. 

    Next, in configureOptions the set Required method as the default group and Default if the switch is checked:

     public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ // ... "validation_groups" => function(FormInterface $form) { if ($form->has("toggle") && $form->get("toggle")->getData() === true) { return ['Default']; // <--- set } return ['Required']; // <--- set }, 'constraints' => [new Assert\Valid()], // <--- set ]); } 

    In this case, when sending with disconnection: Default and Required groups are applied to the address fields, but only the Default group, thus skipping the necessary fields.

Nested forms containing objects disconnected from the root object can be checked by setting the restriction parameter to new Valid() .

+2
source

Source: https://habr.com/ru/post/1270924/


All Articles