I’ve recently started building a new web app and have decided to build it in Symfony (and hopefully ultimately Vue for the front-end), as a way of learning what looks like a really cool framework. I’d had an introduction to Symfony through work, then did some online courses, including a load of the excellent SymfonyCasts, so have a reasonable amount of knowledge now on the subject.
One cool feature of Symfony is its form handling abilities. Using simple annotations and generated code, you can get alot of functionality around submitting, validating and saving your form data for very little effort. When rendering a form to the user, Symfony’s template handler, Twig, has a load of built in functions to render each field, such as form_widget
to display the field’s HTML tag, form_label
to display a field’s label, form_row
to combine the above 2 and 2 more, etc. These can be overwritten, so you can style/theme your form using your own CSS, while keeping Symfony and Twig’s powerful form functionality. More details can be found on Symfony’s form customization page.
One thing I found was that sometimes you don’t really need to modify the original form_widget
, you just need to say wrap its contents in a div
with a specific class
. So, ideally there’d be a way to overwrite form_widget
but still call the parent/original one. Luckily there is, but it was a little tricky to figure out.
Let’s say I need to add a <div class="select">
around a particular field. For this, we can overwrite the choice_widget
function, which generates <select>
tags. In your form theme you can do something like:
1 2 3 4 5 | {% block choice_widget %} <div class="select"> {{ parent() }} </div> {% endblock choice_widget %} |
And you’d think that would work no issues! However, I kept getting errors along the lines of “Can’t call parent function” or “parent function does not exist”, or something like that. I found it surprising, because you can simply call choice_widget
before you add your code to overwrite it, so the function must be in the global scope, right? Well, somehow it isn’t! Luckily the fix is simple: import the base Twig theme at the top of your own theme:
1 | {% use 'form_div_layout.html.twig' %} |
And voilá! You should now have your select
wrapped in its stlystyled div
.