Cover of the book Symfony 5: The Fast Track

Symfony 5: The Fast Track is the best book to learn modern Symfony development, from zero to production. +300 pages showcasing Symfony with Docker, APIs, queues & async tasks, Webpack, SPAs, etc.

New in Symfony 5.2: Form field helpers

Contributed by
Titouan Galopin
in #38307.

Symfony Forms helps you create and process HTML forms by abstracting all the hard and repetitive stuff. It also provides many utilities to render form contents, from the render-all {{ form(form) }} instruction to the individual form helpers:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{{ form_start(form) }}
    <div class="my-custom-class-for-errors">
        {{ form_errors(form) }}
    </div>

    <div class="form-control">
        <i class="fa fa-calendar"></i> {{ form_label(form.dueDate) }}
        {{ form_widget(form.dueDate) }}

        <small>{{ form_help(form.dueDate) }}</small>

        <div class="form-error">
            {{ form_errors(form.dueDate) }}
        </div>
    </div>
{{ form_end(form) }}

The form_*() helpers render each part of the form field, including all its needed HTML elements. Most developers like this behavior, but some designers struggle with it, because it hides all the HTML in form themes which are not easy to manage by them.

That’s why Symfony 5.2 introduces new Twig form helpers to render the value of each form field part without adding any HTML around it:

  • field_name
  • field_value
  • field_label
  • field_help
  • field_errors
  • field_choices (an iterator of the field choices; e.g. for <select>)

When using these helpers, you must write all the HTML contents for all form fields, which some people prefer to better control the generated HTML without having to deal with form themes:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<input
    name="{{ field_name(form.username) }}"
    value="{{ field_value(form.username) }}"
    placeholder="{{ field_label(form.username) }}"
    class="form-control"
/>

<select name="{{ field_name(form.country) }}" class="form-control">
    <option value="">{{ field_label(form.country) }}</option>

    {% for label, value in field_choices(form.country) %}
        <option value="{{ value }}">{{ label }}</option>
    {% endfor %}
</select>
Help the Symfony project!

As with any Open-Source project, contributing code or documentation is the most common way to help, but we also have a wide range of sponsoring opportunities.

Comments

It's great to have more flexibility here, thank you for this nice addition!

Just a technical details: at which point will be form field be considered as "rendered"? After calling `field_value`? Can `field_value` be called many times (of instance for the select example, to select the correct option)?
Hello @Romain!

It's based on the field_name function: once called, the field is considered rendered.
Am I right to assume that I have to manually define the selected state for elements?
@Daniel yes, indeed! If you're using value inputs (text, date, textarea, ...) a direct call to form_value is enough. For choice inputs (select, radio, checkbox, ...) it requires a little bit more work to iterate over the choices and check if the choice is currently selected, but nothing too difficult.
Really appreciate this feature. Much easier than putting in overrides. Such much to look forward to in 5.2
Nice! A good alternative to themes for lighter needs
Nice ! But how it's work with nesteed forms ?
dot call : field_name(form.person.username)
tab call : field_name(form.person[username])
other ?
Login with SymfonyConnect to post a comment