Custom form field template with twig

Viewed 6743

I'd like to create a custom template in twig to render a form field.

Example:

{{ form_row(form.field) }}

This can be overriden by form theming

{% block form_row %}
... custom code
{% endblock form_row %}

What I would like to do is this:

{% block custom_row %}
... custom code
{% endblock custom_row %}

and use it like this:

{{ custom_row(form.field }}

however, this throws an exception that method custom_row is not found.

My understanding is that this can be done with Twig extension, but I don't know how to register a block to be a function.

Update

what I actually want:

I use twitter bootstrap and a bundle which overrides all the form themes. And it renders a div around a radio, so it can't be inlined. So I wanted to do something like this:

copy their template and get rid of the div:

{% block inline_radio_row %}
    {% spaceless %}
        {% set col_size = col_size|default(bootstrap_get_col_size()) %}

        {% if attr.label_col is defined and attr.label_col is not empty %}
            {% set label_col = attr.label_col %}
        {% endif %}
        {% if attr.widget_col is defined and attr.widget_col is not empty %}
            {% set widget_col = attr.widget_col %}
        {% endif %}
        {% if attr.col_size is defined and attr.col_size is not empty %}
            {% set col_size = attr.col_size %}
        {% endif %}

        {% if label is not sameas(false) %}
            {% if not compound %}
                {% set label_attr = label_attr|merge({'for': id}) %}
            {% endif %}
            {% if required %}
                {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
            {% endif %}
            {% if label is empty %}
                {% set label = name|humanize %}
            {% endif %}
            {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' radio-inline')|trim}) %}
            <label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}>
                {{ block('radio_widget') }}
                {{ label|trans({}, translation_domain) }}
            </label>
        {% else %}
            {{ block('radio_widget') }}
        {% endif %}
        {{ form_errors(form) }}
    {% endspaceless %}
{% endblock inline_radio_row %}

and then

{{ inline_radio_row(form.field) }}

I ended up just overriding the whole theme, and added ifs around the div in question, a the class (radio-inline). But I'm still wondering if there's a way to make this work. Seems like it makes you work so hard for something so simple.

Update 2

I found the functionality:

class FormExtension extends \Twig_Extension
{
    public function getFunctions()
    {
        return array(
            'inline_radio_row'  => new \Twig_Function_Node(
                'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode',
                array('is_safe' => array('html'))
            ),
        );
    }
}

This does exactly what I want, but it says it's deprecated. Anyone knows an updated version of how to use this?

Update 3

Similar functionality can be also achieved with http://twig.sensiolabs.org/doc/tags/include.html

2 Answers
Related