Avoid twig block output - symfony

I have the following twig template
{%- block block1 -%}
<div class="test">
{{ block('block2') }}
</div>
{%- endblock block1 -%}
{%- block block2 -%}
<div>Test2</div>
{%- endblock block2 -%}
The Result is:
<div class="test">
<div>Test2</div>
</div><div>Test2</div>
But should be:
<div class="test">
<div>Test2</div>
</div>
I want todo something like the form template in symfony: https://github.com/symfony/symfony/blob/2.7/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
UPDATE:
The only solution would be to add an if false which looks not very nice:
{%- block block1 -%}
<div class="test">
{{ block('block2') }}
</div>
{%- endblock block1 -%}
{% if false %}
{%- block block2 -%}
<div>Test2</div>
{%- endblock block2 -%}
{% endif %}

Why do you want to define your blocks this way? Or put it in other words: You can simply define the second block inside the first block like this:
{%- block block1 -%}
<div class="test">
{%- block block2 -%}
<div>Test2</div>
{%- endblock block2 -%}
</div>
{%- endblock block1 -%}

If you separate the result you get in a different way, it will help you see what is happening:
// block1 with block2 inserted
<div class="test">
<div>Test2</div>
</div>
// block2
<div>Test2</div>
i.e. when you define block2 it is not only inserted into block1, it is also rendered at the place where it is defined. You may try to build this functionality some other way, perhaps by using the include function

you have to add your form theme to render these custom blocks or like Carlos Granados saying you have to include other twig here.
Which link you are showing is symfony2 form theme which will render when form blocks will call and it is doing it because you tell symfony2 to do it. In your layout twig add file like this -
{% form_theme form "UrBundle:Default:fields.html.twig" %}
it will be your file which will render your blocks - fields.html.twig,
here you can define your blocks and then can access those in current like -
{% block block1 %}
{{ parent() }}
{% endblock %}
it's out will be like you want link

In twig, the main template rendered will always render all of the blocks "included" in the template, even with extends. Instead you're attempting to create horizontal reuse blocks.
In order to produce your desired result, you would need to implement a {% use 'blocks.twig' %}
This approach is highly subjective to what you intend to accomplish and is not typically needed in regular templates.
Example https://twigfiddle.com/fwjpl8
{# main.html.twig #}
{% use 'info.blocks.twig' %}
{%- block content -%}
{%- set data = { name: 'Test', place: 'Test2' } -%}
{{ block('data') }}
{%- endblock -%}
{# info.blocks.twig #}
{%- block data -%}Data {{ data.name }} {{ block('data_place') }}{%- endblock -%}
{%- block data_place -%}{{ data.place }}{%- endblock -%}
Result:
Data test test2
Do keep in mind there are limitations on use.
The use tag only imports a template if it does not extend another
template, if it does not define macros, and if the body is empty. But
it can use other templates.
So you can not do
{# main.html.twig #}
{% use 'info.blocks.twig' %}
{# info.blocks.twig #}
{% extends 'other.blocks.twig' %}
{%- block data -%}Data {{ data.name }} {{ block('data_place') }}{%- endblock -%}
{%- block data_place -%}{{ data.place }}{%- endblock -%}

Related

Symfony form theme conflict

I have two forms in the same template page, where I need to apply for each form one specific theme. Unfortunately the first theme override the second one.
So that the second theme is not applied at all.
Another thing, in pages where I only have the form_subscribe form, the second theme is well applied for that form. The problems comes only when I have tow forms in the same page.
First Form:
{% form_theme form '#ezdesign/_form/bootstrap_full_form_theme.html.twig' %}
{{ form_start(form) }}
{{ form_end(form) }}
Second Form:
{% form_theme form_subscribe '#ezdesign/_form/bootstrap_modal_form_theme.html.twig' %}
{{ form_start(form_subscribe) }}
{{ form_end(form_subscribe) }}
It's not necessary to share my template content, anyway:
First theme templae:
{% extends 'bootstrap_4_layout.html.twig' %}
{% block form_row -%}
{%- if compound is defined and compound -%}
{%- set element = 'fieldset' -%}
{%- endif -%}
<{{ element|default('div') }} class="form-group">
{{- form_widget(form) -}}
</{{ element|default('div') }}>
{%- endblock form_row %}
Second Theme template:
{% extends 'bootstrap_4_layout.html.twig' %}
{% block form_row -%}
{%- if compound is defined and compound -%}
{%- set element = 'fieldset' -%}
{%- endif -%}
<{{ element|default('div') }} class="form-group">
<div class="row">
{{- form_label(form, null, {'label_attr': {'class' : 'col-sm-4'}}) -}}
<div class="col-sm-8">
{{- form_widget(form) -}}
</div>
</div>
</{{ element|default('div') }}>
{%- endblock form_row %}
Any idea would be appreciated and voted.
Have your registred your custom form templates in twig config ?
# config/packages/twig.yaml (symfony 4)
# app/config/config.yml (symfony < 4)
twig:
form_themes:
- ...
- '#ezdesign/_form/bootstrap_full_form_theme.html.twig'
- '#ezdesign/_form/bootstrap_modal_form_theme.html.twig'
https://symfony.com/doc/current/form/form_themes.html#applying-themes-to-all-forms
As this could well be a side effect of the caching, and as it seems to be linked to the fact that the two forms are in the exact same template, a way to fix this could be to separate your forms with includes:
some-page.html.twig
{{ include('partial/form.html.twig', { 'form': form }) }}
{{ include('partial/form-subscribe.html.twig', { 'form_subscribe': form_subscribe }) }}
partial/form.html.twig
{% form_theme form '#ezdesign/_form/bootstrap_full_form_theme.html.twig' %}
{{ form_start(form) }}
{{ form_end(form) }}
partial/form-subscribe.html.twig
{% form_theme form_subscribe '#ezdesign/_form/bootstrap_modal_form_theme.html.twig' %}
{{ form_start(form_subscribe) }}
{{ form_end(form_subscribe) }}
This way, you end up with only one form_theme per template, and wouldn't collide your themes as per this comment:
{# this form theme will be applied only to the form of this template #}
Source: https://symfony.com/doc/current/form/form_themes.html#applying-themes-to-single-forms

Using Twig in Symfony 2: Translation inside an embeded block does not work

I am using Twig inside my Symfony 2 WebApp project. I use {% embed SomeTamplate %} to include the content of one template file in another. This workes fine, but translation is not working inside the embedded file.
Page Template:
{% extends 'AppBundle::layout.html.twig' %}
{% trans_default_domain mypages' %}
1: {{ 'pages.home.sometext'|trans }}
{% embed "block.html.twig" with {'classes': 'homepage-hero'} %}
{% block content %}
2: {{ 'pages.home.sometext'|trans }}
{% endblock %}
{% endembed %}
{% embed "block.html.twig" with {'classes': 'red-bg'} %}
{% block content %}
3: {{ 'pages.home.sometext'|trans }}
{% endblock %}
{% endembed %}
Block template:
{% trans_default_domain mypages' %}
<div class="full-width-block{% if classes is defined %} {{ classes }}{% endif %}">
X: {{ 'pages.home.sometext'|trans }}
{% block content %}
{% endblock %}
</div>
Output:
1: SomeText
X: SomeText
2: pages.home.sometext
X: SomeText
3: pages.home.sometext
So: While the translation works fine within the two template files, the same text constant within the embedded block, is not translated. How can I fix this?
the domain must be enclosed in quotes, just put the last quotation mark.
Visit http://symfony.com/doc/current/book/translation.html
Put it this way:
{% trans_default_domain "mypages" %}
I hope your problem is solved

Symfony2, a label Token appears when using form themes

I'm using Symfony2.6 , and I'm trying to customize form rendering. The problem that when I put {{ form_rest(form) }} into the form , a label Token appears. How can I make it hidden ?
This is the form theme
{% extends 'form_div_layout.html.twig' %}
{% block form_widget_simple %}
<div class="form-group">
{{ form_label(form, null, {'label_attr': {'class': 'control-label'}}) }}
{{ parent() }}
</div>
{% endblock %}
When I remove the block {% block form_widget_simple %} to test what gives , the Token label become hidden.
Edit:
I'd like to know also if it's correct to change the simple widget block and render inside it a label or no.
You've changed the block of the simple widget which shouldn't render a label (and it doesn't by default). If you really need to do it this way, you may check the type variable and do not render label for the hidden type. Something as following:
{% block form_widget_simple %}
<div class="form-group">
{% if type != 'hidden' %}
{{ form_label(form, null, {'label_attr': {'class': 'control-label'}}) }}
{% endif %}
{{ parent() }}
</div>
{% endblock %}
This works fine :
{% extends 'form_div_layout.html.twig' %}
//........
{%- block hidden_row -%}
<div style="display:none">
{{ form_widget(form) }}
</div>
{%- endblock hidden_row -%}

Is a Twig block empty? - Symfony 2

I have a twig template with the following block:
{% block dashboard %}
{% include "::user_dashboard.html.twig" %}
{% endblock dashboard %}
Later in that template, I want to set a class on a div based on whether or not there is anything in that block (i.e., by default, it will have the include above, but children of this template may override it and empty it out).
What I had (that somewhat worked) was ...
{% set _dashboard = block('dashboard') %}
{% set _mainWidth = ( _dashboard|trim is empty ? "no-dashboard" : "with-dashboard" ) #}
<div id="main" class="{{ _mainWidth }}">
The problem here is that whole dashboard block gets called twice. This wouldn't bother me too much except that block renders a few controller actions, i.e. ...
{% render "UserWidget:userAppMenu" %}
... and the code in that action is being called twice. For various reasons, not the least of which is performance, this messes with some of the stuff in that dashboard block.
So, my question is ... is there any way to tell if that block is empty without loading it twice? Is there something really simple I'm missing or is this even possible?
Thanks!
EDIT:
Here is my full template if it helps clarify things:
{% extends '::base.html.twig' %}
{% block layout %}
{% block header %}
{% include "::header.html.twig" %}
{% endblock header %}
<div id="container" class="row-fluid">
{% block dashboard %}
{% include "::user_dashboard.html.twig" %}
{% endblock dashboard %}
{% set _dashboard = block('dashboard') %}
{% set _mainWidth = ( _dashboard|trim is empty ? "no-dashboard" : "with-dashboard" ) %}
<div id="main" class="{{ _mainWidth }}">
<h1 class="page-title">{% block page_title %}{% endblock %}</h1>
{% block main_filters %}{% endblock %}
{% if app.session.flashbag.has('message') %}
<div class="alert alert-block alert-success">
<ul>
{% for flashMessage in app.session.flashbag.get('message') %}
<li>{{ flashMessage }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% if app.session.flashbag.has('warning') %}
<div class="alert alert-block alert-success">
<ul>
{% for flashWarning in app.session.flashbag.get('warning') %}
<li>{{ flashWarning }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% block body %}{% endblock %}
{% block footer %}
{% include "::footer.html.twig" %}
{% endblock footer %}
</div>
</div>
{% endblock layout %}
Here you can see on lines 11 and 15 - both of those actually seem to include and process what is in that include.
What about this? This way the block should only be rendered once, when you call block('dashboard').
{# at top of twig #}
{% set _dashboard = block('dashboard') %}
{# where ever you include your block #}
<div>
{{ _dashboard|raw }}
</div>
{# and your main #}
{% set _mainWidth = ( _dashboard|trim is empty ? "no-dashboard" : "with-dashboard" ) #}
<div id="main" class="{{ _mainWidth }}">

How can you output HTML as entities in Twig?

I have widget examples that I need to output the HTML of so that people can copy and paste them onto their own websites. How can I escape the output so that it doesn't get rendered?
Ended up doing this, the key to the problem is using the escape filter as a block, the rest accounts for need for no spaces around <pre/><code/>'s to get the desired output:
<pre>
{%- spaceless -%}
<code>
{%- filter escape -%}
{% spaceless %}
{% include 'ACMEDemoBundle:Example:widget.html.twig' %}
{% endspaceless %}
{%- endfilter -%}
</code>
{%- endspaceless -%}
</pre>

Resources