Disable the HTML5 validation of all your Symfony forms with a feature flag
Published on 2019-06-29 • Modified on 2019-07-01
In this post, we will see how to implement a simple feature flag. This flag will help us to debug our forms and will allow to disable the HTML5 client side validation of all the forms of an application. Let's go! 😎
» Published in "A week of Symfony 653" (1-7 July 2019).
Configuration
- PHP 8.4
- Symfony 6.4.16
Introduction
When you are working on the backend validation of a form Type, it's easier to debug if the HTML5 validation is disabled. You can do this by adding to your form a novalidate
attribute in your Twig template:
{{ form_start(form, {attr: {'novalidate': 'novalidate'}}) }}
A small trick here: You can declare an invalid attribute to restore the validation. It's easier than removing it entirely. But not very clean, as your form will have an invalid and useless attribute that will not be interpreted by the browser.
{{ form_start(form, {attr: {'novalidate-off': 'novalidate'}}) }}
You can also declare this attribute directly in your form type, in this case you can comment the line to activate or not the validation:
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'attr' => [
'novalidate' => 'novalidate', // comment me to reactivate the html5 validation! 🚥
]
]);
}
It works but it's a manual task and this "debugging code" could be forgotten. So let's see how we could automate this process, not only for a specific form but for all the forms of your application.
Creating the feature flag
So first, let's create the feature flag. Let make it very simple, it will be a boolean parameter in the service container.
# config/posts/29.yaml (imported in config/services.yaml)
parameters:
html5_validation: '%env(bool:APP_HTML5_VALIDATION)%'
We need to bind this parameter so we can inject it in a service:
# config/services.yaml
services:
_defaults:
bind:
$html5Validation: '%html5_validation%'
Now we can use this variable to inject it in a service. Let's create our type extension that will be responsible to enable or not the feature.
Creation of the new type extension
The goal here will be to add a global form type extension that will be used by all our FormType
classes. Create the following file. Thanks to the Symfony auto-loading it will be automatically used by the application. Moreover, this service will be tagged as a form type extension as it implements the AbstractTypeExtension
.
<?php
declare(strict_types=1);
// src/Form/Extension/NoValidateExtension.php
namespace App\Form\Extension;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
class NoValidateExtension extends AbstractTypeExtension
{
private bool $html5Validation;
public function __construct(bool $html5Validation)
{
$this->html5Validation = $html5Validation;
}
/**
* @param array<string,mixed> $options
*/
public function buildView(FormView $view, FormInterface $form, array $options): void
{
$attr = !$this->html5Validation ? ['novalidate' => 'novalidate'] : [];
$view->vars['attr'] = array_merge($view->vars['attr'], $attr);
}
public static function getExtendedTypes(): iterable
{
return [FormType::class];
}
}
As you can see, we save the flag state and depending of its value we add the novalidate
attribute to the form with the help of $view->vars['attr']
of the buildView
method. The nominal value of the flag is true. When wanting to turn off the validation switch the flag to false. But do you see the problem? If you commit the value to false then your application in production will have all the client side validation disabled. Even if the website would work thanks to the backend validation, this is probably something you don't want to do.
To make this parameter dependent to the environment, we will move it in the .env
file located at the root of the project. Thus, in production we will put this value to true (1) and won't touch it any-more. On the other hand, we will able to easily switch the value as we need. Add the following parameter in your .env
file:
# .env and .env.dist
APP_HTML5_VALIDATION=true
In the services.yml
file, let's modify the raw parameter value by the one we've just introduced:
# config/services.yaml
parameters:
html5_validation: '%env(bool:APP_HTML5_VALIDATION)%'
You will notice here that we used the bool
preprocessor in order to make the .env
component to handle this variable as a boolean and not like a string.
Without this preprocessing, if we put false for the value, this one will be interpreted as true because the type hint of our extension constructor expects a boolean: __construct(bool $htm5Validation)
. Test to see! Or you can also put 0 or 1 without using the preprocessor.
Now we are sure this value will stay to true in production but we will able to easily modify it when developing.
That's it! I hope you like it. Check out the links below to have additional information related to the post. As always, feedback, likes and retweets are welcome. (see the box below) See you! COil. 😊
The Symfony doc More on Stackoverflow More on the web
They gave feedback and helped me to fix errors and typos in this article; many thanks to ro0NL, jmsche.
Call to action
Did you like this post? You can help me back in several ways: (use the "reply" link on the right to comment or to contact me )
- Report any error/typo.
- Report something that could be improved.
- Like and repost!
- Follow me on Bluesky 🦋
- Subscribe to the RSS feed.
- Click on the More on Stackoverflow buttons to make me win "Announcer" badges 🏅.
Thank you for reading! And see you soon on Strangebuzz! 😉
