How can i pass parameters to a Symfony2 Twig block?
Asked Answered
C

10

28

I want to generate table headers in a twig block and reuse them across the page, this page has about 5 different tables with roughly the same headers. The block code is such :

{% block table_headers %}
    <th>Fiscal Year</th>
    <th>End Date</th>
    <th>Period Length</th>
    {% for item in result.FinancialStatements.COAMap.mapItem %}
        {% if item.statementType == statementType %}
            <th>{{ item._ }} ({{ item.coaItem }})</th>
        {% endif %}
    {% endfor %} 
{% endblock %}

The key line in the above code is

{% if item.statementType == statementType %}

I want to pass the statementType as parameter where i am rendering the block, like so :

{% render block.table_headers with {'statementType': 'INC'} %}

But this doesn't work. I want to keep the block and its rendering in the same file (but different blocks), for conceptual closeness.

Is it even possible to use blocks like this? I've looked at the Symfony2 docs and couldn't find anything that suggested this could be done, but it seems such an obvious use of blocks to me.

Cuttler answered 20/5, 2011 at 6:58 Comment(0)
V
13

There is an update to the include tag in Symfony 2.2 which might help you with this. Here's an example of the new tag: {{ include('FTWGuildBundle:Help:popover.html.twig', {'content':helpContent,'title':helpTitle}) }}

This may be what you need, since it avoids having to do a sub-request to a controller (render does this) it will be better performing.

In my example, I'm including the HTML for a help popover and providing the title and content.

Villada answered 12/4, 2013 at 20:49 Comment(3)
I wish this feature was there when i first posted the question in 2011. +1Cuttler
Thanks - this was exactly what I was looking for and meant that I did not have to add any routes in routing.yml.Antineutrino
Outdated in later versions of Twig, use the alternative that uses the 'with' instead of a comma between the parameters and the route.Hillie
V
21

Now with Symfony v2+ (3, 4 & 5, since Twig v1.28.0), we can use a custom template on the block() function using the with keyword:

{% with {
            'myVar1': myValue1,
            'myVar2': myValue2
        }
%}
        {{ block('toolbar', myTemplate) }}
{% endwith %}

Commit: https://github.com/twigphp/Twig/commit/02b084e2f5c3119604b1c0da388dd2438a012191

Venicevenin answered 8/3, 2017 at 8:45 Comment(1)
This works fine for me, especially since with does not override variables out of its scope.Rueful
V
13

There is an update to the include tag in Symfony 2.2 which might help you with this. Here's an example of the new tag: {{ include('FTWGuildBundle:Help:popover.html.twig', {'content':helpContent,'title':helpTitle}) }}

This may be what you need, since it avoids having to do a sub-request to a controller (render does this) it will be better performing.

In my example, I'm including the HTML for a help popover and providing the title and content.

Villada answered 12/4, 2013 at 20:49 Comment(3)
I wish this feature was there when i first posted the question in 2011. +1Cuttler
Thanks - this was exactly what I was looking for and meant that I did not have to add any routes in routing.yml.Antineutrino
Outdated in later versions of Twig, use the alternative that uses the 'with' instead of a comma between the parameters and the route.Hillie
K
8

{% render block.table_headers with {'statementType': 'INC'} %} is not recognized by Symfony. You must use:

{% render "yourBundle:controleur:action" with { 'arg1' : 'value1', 'arg2' : 'value2' } %}
Kriegspiel answered 22/8, 2012 at 15:32 Comment(1)
This embeds a controller, which is definitely what the OP is asking for.Samuelsamuela
P
7

Sounds like you want Twig's macros feature. Alternatively write your block as a separate template and use include.

Provenance answered 3/6, 2011 at 11:58 Comment(1)
I ended up using macros and blocks with global parameters. includes would split up the logic that belongs together into multiple files, i avoided that.Cuttler
E
6

When using the block function, child template has access to parent vars:

{% set foo = 'bar' %}
{{ block('another_block') }}

In child template:

{% block another_block %}
    {{ foo }}
{% endblock %}

Prints:

bar
Elisha answered 28/7, 2020 at 11:36 Comment(0)
D
0

Another would be to create a Twig extension, see

http://symfony.com/doc/current/cookbook/templating/twig_extension.html

Your Twig function taking care of rendering the header

return $this->renderView("MyBundle:Twig:tableHeader.html.twig", array( 'result' => $result));
Driskell answered 23/8, 2012 at 3:10 Comment(0)
V
0

For what it's worth to you. Here's an example of how I've rendered blocks of content. This is for a batch app which sends emails, so its a little different than what you're trying, but none the less may be helpful

        $templateContent = $this->getContainer()->get('twig')->loadTemplate('FTWGuildBundle:AuctionNotification:notificationEmail.html.twig');
        $body = $templateContent->renderBlock('body', array('siteDomain' => $siteClient->getSiteDomain(), 'staticContentDomain' => $siteClient->getStaticContentDomain(), 'batch' => $batch->getNotifications(), 'auction_notification_lockout_period' => $this->getContainer()->getParameter('auction_notification_lockout_period')));
        $subject = ($templateContent->hasBlock("subject")
            ? $templateContent->renderBlock("subject", array('batchSize' => $batch->getSize(), 'batch' => $batch))
            : "Auction House Notifications");
Villada answered 12/4, 2013 at 20:54 Comment(0)
F
0

Call any method of class with parameters without key

{{ attribute(classname, methodname, [parameter1, parameter2]) }}

Call any method of class with parameters with key

{{ attribute(classname, methodname, {"parameter1" : parameter1, "parameter2" : parameter2]) }}

Retrieve property of the array/object

{{ attribute(array, key) }}

Forgetmenot answered 24/7, 2019 at 11:4 Comment(0)
W
0

You can combine block with the with tag.

{%- with {'statementType': 'INC'} -%}
  {{- block('table_headers') -}}
{%- endwith -%}
Willawillabella answered 30/5, 2022 at 8:44 Comment(0)
A
0

Twig allows not only to render block with some data from child template but also add some content to the rendered block. Hope it'll help someone.

Base template

{% block test %}
    {{ dump(test_param|default('no value')) }}
{% endblock %}

Child template

{% block test %}
    {% with {
        test_param: 123
    } %}
        {{ parent() }}
    {% endwith %}

    Some additional content
{% endblock %}

Result

enter image description here

Aurelie answered 12/12, 2022 at 19:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.