Skip to content

[Form] Add "form_attr" FormType option #40430

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 18, 2021

Conversation

cristoforocervino
Copy link
Contributor

@cristoforocervino cristoforocervino commented Mar 9, 2021

Q A
Branch? 5.x
Bug fix? no
New feature? yes
Deprecations? no
Tickets N/A
License MIT
Doc PR #15108

What is this about

This PR add support for form attribute to Symfony Form (browser compatibility).

The form attribute allows form elements to override their associated form (which is their nearest ancestor form element by default). This is extremely useful to solve nested form problem and allows form children to be rendered outside form tag while still working as expected.

New "form_attr" FormType option

form_attr

type: bool or string default: false

If set to true on a root form, adds form attribute on every children with their root form id.
This allows you to render form children outside the form tag and avoid nested form problem in some situations while keeping the form working properly.

If set to true on a child, adds form attribute on it with its root form id.
This allows you to render that child outside the form tag and avoid nested form problem in some situations while keeping the form working properly.

If root form has no id (this may happen by create an unnamed form), you can set it to a string identifier to be used at FormView level to link children and root form anyway.

Usage on Root Form Example

Form Type

Enable the feature by setting form_attr to true on the root form.

use Symfony\Component\Form\Extension\Core\Type;

class ListFilterType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('search', Type\SearchType::class)
            ->add('orderBy', Type\ChoiceType::class, [
                'choices' => [
                    // ...
                ],
            ])
            ->add('perPage', Type\ChoiceType::class, [
                'choices' => [
                    // ...
                ],
            ])
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefault('form_attr', true); // <--- Set this to true
    }
}

Twig

The following Twig template works properly even if form children are outside their form tag (browser compatibility).

<div class="header-filters">
    {{ form_errors(form) }}
    {{ form_row(form.search) }} {# has attribute form="list_filter" #}
    {{ form_row(form.orderBy) }} {# has attribute form="list_filter" #}
</div>

<!-- -->
<!-- Some other HTML content, like a table or even another Symfony form -->
<!-- -->

<div class="footer-filters">
    {{ form_row(form.perPage) }} {# has attribute form="list_filter" #}
</div>
{{ form_start(form) }} {# id="list_filter" #}
{{ form_end(form) }}

✅ Every form elements work properly even outside form tag.

Usage on Form Child Example

Enable the feature by setting form_attr to true on selected child.

use Symfony\Component\Form\Extension\Core\Type;

class ListFilterType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('search', Type\SearchType::class)
            ->add('orderBy', Type\ChoiceType::class, [
                'choices' => [
                    // ...
                ],
            ])
            ->add('perPage', Type\ChoiceType::class, [
                'form_attr' => true,  // <--- Set this to true
                'choices' => [
                    // ...
                ],
            ])
    }
}

Twig

The following Twig template works properly even if form.perPage is outside form tag (browser compatibility).

<div class="header-filters">
    {{ form_start(form) }} {# id="list_filter" #}
        {{ form_errors(form) }}
        {{ form_row(form.search) }}
        {{ form_row(form.orderBy) }}
    {{ form_end(form, {'render_rest': false}) }}
</div>

<!-- -->
<!-- Some other HTML content, like a table or even another Symfony form -->
<!-- -->

<div class="footer-filters">
    {{ form_row(form.perPage) }} {# has attribute form="list_filter" #}
</div>

form.perPage element work properly even outside form tag.

@cristoforocervino cristoforocervino force-pushed the form-attribute branch 2 times, most recently from 5e12bfc to 4b03b5d Compare March 9, 2021 22:48
@cristoforocervino cristoforocervino changed the title [Form] Add FormType form_attr option [Form] Add "form_attr" FormType option Mar 9, 2021
@carsonbot
Copy link

Hey!

I like what you have done here. Keep up the good work.

I think @fancyweb has recently worked with this code. Maybe they can help review this?

Cheers!

Carsonbot

@nicolas-grekas nicolas-grekas added this to the 5.x milestone Mar 16, 2021
@derrabus
Copy link
Member

Thank you @cristoforocervino.

@derrabus derrabus merged commit c8b48d8 into symfony:5.x Mar 18, 2021
wouterj added a commit to symfony/symfony-docs that referenced this pull request Apr 8, 2021
…toforo Cervino, cristoforocervino)

This PR was merged into the 5.3-dev branch.

Discussion
----------

[Form] "form_attr" FormType option documentation

This is the documentation for [#40430](symfony/symfony#40430)

Commits
-------

c8deb3d add form_attr option doc
@fabpot fabpot mentioned this pull request Apr 18, 2021
nicolas-grekas added a commit that referenced this pull request Dec 28, 2022
…Cat)

This PR was merged into the 5.4 branch.

Discussion
----------

[Form] Make `ButtonType` handle `form_attr` option

| Q             | A
| ------------- | ---
| Branch?       | 5.4
| Bug fix?      | Not sure
| New feature?  | Not sure
| Deprecations? | no
| Tickets       | Fix #48794
| License       | MIT
| Doc PR        | N/A

Seems #40430 just forgot about `ButtonType` so I’m basically moving the implementation to `BaseType` and duplicating the tests in `ButtonTypeTest`.

Commits
-------

318a9ae [Form] Make `ButtonType` handle `form_attr` option
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants