Form Rendering Variables

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $12.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

Find the form_row() documentation. There is one super important thing that almost all of these functions share: their last argument is something called variables.

These variables are key to controlling how each part of each field is rendered. And it's explained a bit more at the bottom. Yep - this table describes the most common "variables" - which are kind of like "options" - that you can pass to most fields, including label.

Let's override that variable for the title. Pass a second argument to form_row(): an array with a label key. How about, Article title.

... lines 1 - 5
{{ form_start(articleForm) }}
{{ form_row(articleForm.title, {
label: 'Article title'
}) }}
... lines 10 - 14
{{ form_end(articleForm) }}
... lines 16 - 17

Try that! Reload the form. Boom! Label changed!

Discovering the Form Variables

There are tons of variables that you can pass to the form rendering functions to change how the field is rendered. And the list of those variables will be slightly different for each field type. The best way to see all the possibilities is back inside our best friend: the form profiler.

Click on the field you want to customize - like title. I'll collapse the options stuff. Remember: options are what we can pass to the third argument of the add() function in our form class.

For rendering, we're interested in the "View Variables". Behind the scenes, each part of each field is rendered by a mini Twig template that lives inside Symfony. We'll see this later. These variables are passed to those Twig templates and used to control, well, almost everything.

Hey! There's the label variable we just overrode! Notice, it's null: the values inside the profiler represent the values at the moment the form object is passed into the Twig template. So, if you override a value, it won't show up here. No big deal - just don't let that surprise you.

Ah, and there's a help message and a whole bunch of other things that help the form do its job, like full_name, which will be the name attribute, and even the id attribute.

By the way, if it's useful, in addition to overriding these variables, you can access them directly in your template. I don't need it here, but you could, for example print

If you go back and look at your form, that will print the id attribute that's used for the form field. Pretty cool, though, the real purpose of variables is to override them via the form functions.

form_label(), form_widget(), form_help(), form_errors()

Using form_row() gave us more flexibility, because we can reorder the fields and override the field's variables. If you need a little bit more flexibility, another option is to render the 4 components of each field independently.

For example, get rid of form_row. And, instead, render each part manually: {{ form_label(articleForm.title) }}, and for this function, the second argument is the label. Then {{ form_errors(articleForm.title) }} for the validation errors, {{ form_widget(articleForm.title }} to print the input field, and finally {{ form_help(articleForm.title }}.

... lines 1 - 6
{{ form_label(articleForm.title, 'Article title') }}
{{ form_errors(articleForm.title) }}
{{ form_widget(articleForm.title) }}
{{ form_help(articleForm.title) }}
... lines 11 - 19

Let's see how this compares to using form_row(). Refresh! Hmm - it's almost the same. But if you look more closely, of course! The other fields are wrapped in a form-group div, but the title no longer has that!

When you render things at this level, you start to lose some of the special formatting that form_row() gives you. Sure, it's easy to re-add that div. But form_row also adds a special error class to that div when the field has a validation error.

For that reason, let's go back to using form_row().

... lines 1 - 6
{{ form_row(articleForm.title, {
label: 'Article title'
}) }}
... lines 10 - 17

A little bit later, we're going to learn how we can use form_row(), but completely customize how it looks for one specific form, or across your entire site! We'll do this by creating a "form theme". It's kind of the best of both worlds: you can render things in the lazy way, but still have the control you need.

But before we get there - let's learn how to create an "edit" form so we can update articles!

Leave a comment!

  • 2020-04-01 Diego Aguiar

    Hey Deniz Cetin

    If you define the label in the FormType class, then you can reuse it without worrying about labels. You want to override the predefined label in your templates whenever you need to show a different text. About translations, it should not affect if you use the translation key as the label text


  • 2020-03-31 Deniz Cetin

    Does it make a difference if you define the label in your ArticleFormType.php? What advantages does each side have? Why would I want to define those in Twig, but not the other way around? Does it affect translations?

  • 2020-03-04 Diego Aguiar

    Hey @wuwu

    You can change the label directly in your form class
    or in the template by sending an object with the options as second parameter


  • 2020-03-04 wuwu

    I know how to change the label on form_start() since it has single element.
    How do i change the label with form_widgets() when it has multiple options(password, repeat_password)?

  • 2019-04-03 Victor Bocharsky

    Hey Mike,

    Yeah, you can do it, just create a custom Twig function and return a proper form view from there, then just render it as you always do. You can handle this for with JS, or you can submit it as a normal form to a specific route you created that would handle the form data and where you would redirect user back to the referer URL. Well, I think submitting the form via AJAX request is more cool, but not too imtportant, depends on your needs.


  • 2019-04-02 mike

    how can I place a subscribtion form with a text bar and a submit button which can persist the email in database in the base twig so it can be shown in every page.