Calling parent function in Symfony/Twig form theme

17th November, 2020 - Posted by david

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:

{% 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 with the text

Block “choice_widget” should not call parent() in “xxx.html.twig” as the block does not exist in the parent template “base.html.twig”

. I found it surprising, because you can simply call choice_widget before you add your own 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:

{% use 'form_div_layout.html.twig' %}

And voilá! You should now have your select wrapped in its styled div.

Tags: php symfony twig | david | 17th Nov, 2020 at 22:31pm | No Comments

No Comments

Leave a reply

You must be logged in to post a comment.