From 53ab5b4ad1d938b03a00c5bdc63f1f6e7e826616 Mon Sep 17 00:00:00 2001 From: Simon R Jones Date: Thu, 1 Oct 2026 11:40:49 +0100 Subject: [PATCH 1/4] Add do_not_render option to skip form elements in rendered HTML form --- docs/README.md | 27 +++++++++++++++++++ phpunit.xml.dist | 30 ++++++++++----------- src/Form.php | 21 +++++++++++++++ tests/DoNotRenderTest.php | 56 +++++++++++++++++++++++++++++++++++++++ tests/ExampleTest.php | 12 --------- tests/TwigTrait.php | 49 ++++++++++++++++++++++++++++++++++ 6 files changed, 168 insertions(+), 27 deletions(-) create mode 100644 tests/DoNotRenderTest.php delete mode 100644 tests/ExampleTest.php create mode 100644 tests/TwigTrait.php diff --git a/docs/README.md b/docs/README.md index 42c7c52..94f848f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -34,6 +34,33 @@ To notify a user of an error with their form submission: Symfony Form will automatically display an error message next to the input field. Error messages should have a unique ID and be associated with the form input via the `aria-describedby` attribute. This is provided in the accessible form theme. +## Form options + +### do_not_render + +If you want to add a form field for validating request data, but you don't want to display this in your HTML form, you can use the 'do_not_render' option. +This accepts an array of element names to not render in the form HTML. This can be useful for things like pagination, that don't appear in the main form HTML but appear as links separately on the page. + +Using this example, when the form is rendered to the view template, the page form element is skipped: + +```php +// Form class +class MySearchForm extends AbstractType +{ + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('keywords', TextType::class) + ->add('page', IntegerType::class, ['required' => false]) + ; + } +} +// Controller +$form = $this->createForm(MySearchForm::class, null, ['do_not_render' => ['page']]); +``` + +Please note, an alternative way to achieve this is to use the [allow_extra_fields](https://symfony.com/doc/current/reference/forms/types/form.html#allow-extra-fields) option, which allows additional fields to be passed into a form, but you need to take care of validation yourself. + ## Docs - [Using accessible forms with Laravel](laravel.md) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index b651543..9d0cad9 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,18 +1,18 @@ - - - - src - - - - - - - - - tests - - + + + + + + + + tests + + + + + src + + diff --git a/src/Form.php b/src/Form.php index 97a0e32..f835ceb 100644 --- a/src/Form.php +++ b/src/Form.php @@ -3,6 +3,8 @@ namespace Studio24\AccessibleForms; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\FormInterface; +use Symfony\Component\Form\FormView; use Symfony\Component\OptionsResolver\OptionsResolver; class Form extends AbstractType @@ -16,8 +18,27 @@ public function configureOptions(OptionsResolver $resolver) { parent::configureOptions($resolver); + // Disable HTML5 validation $resolver->setDefaults([ 'attr' => ['novalidate' => 'novalidate'], + 'do_not_render' => [], ]); + + $resolver->setAllowedTypes('do_not_render', 'array'); + } + + /** + * @return void + */ + public function finishView(FormView $view, FormInterface $form, array $options) + { + // Remove elements we do not want to render in HTML form + if (!empty($options['do_not_render'])) { + foreach ($options['do_not_render'] as $element) { + unset($view->children[$element]); + } + } + + parent::finishView($view, $form, $options); } } diff --git a/tests/DoNotRenderTest.php b/tests/DoNotRenderTest.php new file mode 100644 index 0000000..207807c --- /dev/null +++ b/tests/DoNotRenderTest.php @@ -0,0 +1,56 @@ +add('keywords', TextType::class) + ->add('filters', ChoiceType::class, [ + 'choices' => ['Yellow' => 'Yellow', 'Orange' => 'Orange', 'White' => 'White'], + 'expanded' => true, + 'multiple' => true, + ]) + ->add('page', IntegerType::class, ['required' => false]) + ; + } +} + +/** + * Checks that fields listed in the `do_not_render` option are excluded from the + * actual rendered HTML output, not just removed from the FormView tree. + * + * @see https://docs.phpunit.de/en/12.4/writing-tests-for-phpunit.html + */ +class DoNotRenderTest extends TypeTestCase +{ + use TwigTrait; + + public function testDoNotRenderExcludesFieldFromHtml() + { + $options = [ + 'do_not_render' => ['page'] + ]; + $form = $this->factory->create(DoNotRenderTestForm::class, null, $options); + $view = $form->createView(); + $html = $this->renderForm($view); + + /** + * Form element HTML is expected to be: + * + */ + $this->assertStringNotContainsString(' '{{ form(view) }}']), + new FilesystemLoader([ + __DIR__ . '/../vendor/symfony/twig-bridge/Resources/views/Form', + __DIR__ . '/../src/Resources/views/Form', + ]), + ]); + + $twig = new Environment($loader); + $twig->addExtension(new AccessibleFormsExtension()); + $twig->addExtension(new FormExtension()); + $twig->addExtension(new TranslationExtension()); + + $renderer = new FormRenderer(new TwigRendererEngine(['accessible-forms.html.twig'], $twig)); + $twig->addRuntimeLoader(new FactoryRuntimeLoader([ + FormRenderer::class => fn () => $renderer, + ])); + + return $twig->render('index.html.twig', ['view' => $view]); + } +} From 64d82a5d0683dfaaeead904507500222f6ab8ec1 Mon Sep 17 00:00:00 2001 From: Simon R Jones Date: Thu, 1 Oct 2026 11:48:33 +0100 Subject: [PATCH 2/4] Update phplint --- .github/workflows/php.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index ffe565b..d4443fc 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -37,7 +37,7 @@ jobs: # https://github.com/marketplace/actions/check-php-syntax-errors - name: Check PHP syntax errors - uses: overtrue/phplint@9 + uses: overtrue/phplint@9.7.2 - name: Coding standards run: ./vendor/bin/phpcs From 36f5638454fe992abf59fcc296eca3725be2a043 Mon Sep 17 00:00:00 2001 From: Simon R Jones Date: Thu, 1 Oct 2026 11:57:41 +0100 Subject: [PATCH 3/4] coding standards --- .github/workflows/php.yml | 2 +- src/FieldTypes/Html.php | 2 ++ src/Form.php | 2 ++ src/Twig/AccessibleFormsExtension.php | 3 +-- tests/DoNotRenderTest.php | 5 ++--- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index d4443fc..d96ead8 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -11,7 +11,7 @@ jobs: strategy: matrix: - php-versions: ['8,2', '8.3', '8.4'] + php-versions: ['8.2', '8.3', '8.4'] runs-on: ubuntu-latest diff --git a/src/FieldTypes/Html.php b/src/FieldTypes/Html.php index e24e6e2..12ee879 100644 --- a/src/FieldTypes/Html.php +++ b/src/FieldTypes/Html.php @@ -1,5 +1,7 @@ children as $child) { if (isset($child->vars['errors']) && count($child->vars['errors']) > 0) { - $id = $child->vars['id']; if (!empty($child->vars['choices']) && !empty($child->vars['expanded']) && $child->vars['expanded'] === true) { @@ -114,5 +114,4 @@ public function prefixOnErrors(string $string, FormView $form, string $prefix = } return $string; } - } diff --git a/tests/DoNotRenderTest.php b/tests/DoNotRenderTest.php index 207807c..8716e6d 100644 --- a/tests/DoNotRenderTest.php +++ b/tests/DoNotRenderTest.php @@ -11,8 +11,8 @@ use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Test\TypeTestCase; -class DoNotRenderTestForm extends Form { - +class DoNotRenderTestForm extends Form +{ public function buildForm(FormBuilderInterface $builder, array $options): void { $builder @@ -52,5 +52,4 @@ public function testDoNotRenderExcludesFieldFromHtml() */ $this->assertStringNotContainsString(' Date: Thu, 1 Oct 2026 13:12:47 +0100 Subject: [PATCH 4/4] feat: adding do_not_render form option to skip form elements in rendered HTML - Moving docs --- docs/README.md | 27 +-------------------------- docs/form-options.md | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 26 deletions(-) create mode 100644 docs/form-options.md diff --git a/docs/README.md b/docs/README.md index 94f848f..afe62d5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -34,37 +34,12 @@ To notify a user of an error with their form submission: Symfony Form will automatically display an error message next to the input field. Error messages should have a unique ID and be associated with the form input via the `aria-describedby` attribute. This is provided in the accessible form theme. -## Form options - -### do_not_render - -If you want to add a form field for validating request data, but you don't want to display this in your HTML form, you can use the 'do_not_render' option. -This accepts an array of element names to not render in the form HTML. This can be useful for things like pagination, that don't appear in the main form HTML but appear as links separately on the page. - -Using this example, when the form is rendered to the view template, the page form element is skipped: - -```php -// Form class -class MySearchForm extends AbstractType -{ - public function buildForm(FormBuilderInterface $builder, array $options): void - { - $builder - ->add('keywords', TextType::class) - ->add('page', IntegerType::class, ['required' => false]) - ; - } -} -// Controller -$form = $this->createForm(MySearchForm::class, null, ['do_not_render' => ['page']]); -``` - -Please note, an alternative way to achieve this is to use the [allow_extra_fields](https://symfony.com/doc/current/reference/forms/types/form.html#allow-extra-fields) option, which allows additional fields to be passed into a form, but you need to take care of validation yourself. ## Docs - [Using accessible forms with Laravel](laravel.md) - [Using accessible forms with Symfony](symfony.md) +- [Form options](form-options.md) - Form helpers to create a form - Accessible form theme - GOV.UK Design System form theme diff --git a/docs/form-options.md b/docs/form-options.md new file mode 100644 index 0000000..64e15c2 --- /dev/null +++ b/docs/form-options.md @@ -0,0 +1,26 @@ +# Form options + +## do_not_render + +If you want to add a form field for validating request data, but you don't want to display this in your HTML form, you can use the 'do_not_render' option. +This accepts an array of element names to not render in the form HTML. This can be useful for things like pagination, that don't appear in the main form HTML but appear as links separately on the page. + +Using this example, when the form is rendered to the view template, the page form element is skipped: + +```php +// Form class +class MySearchForm extends AbstractType +{ + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('keywords', TextType::class) + ->add('page', IntegerType::class, ['required' => false]) + ; + } +} +// Controller +$form = $this->createForm(MySearchForm::class, null, ['do_not_render' => ['page']]); +``` + +Please note, an alternative way to achieve this is to use the [allow_extra_fields](https://symfony.com/doc/current/reference/forms/types/form.html#allow-extra-fields) option, which allows additional fields to be passed into a form, but you need to take care of validation yourself.