Conditional template inheritance does not work in Symfony 4 - twig

I want a template to inherit a base template when user is not logged in and other template when user is logged in.
I tried several things. One of the obvious is this attempt:
{% extends app.user == null ? 'base.html.twig' : 'protected.html.twig' %}
Other attempt:
{% extends app.user ? 'protected.html.twig' : 'base.html.twig' %}
And so on... nothing works. Always base.html.twig is used.
When I display {{ app.user }} value, the correct value is shown (username or empty if logged in or not logged in, respectively)
Any ideas?
EDIT:
This is the full template I need to be conditional, depending if the user is logged in or not.
{% extends app.user ? 'protected.html.twig' : 'base.html.twig' %}
{% block title %}Inicio{% endblock %}
{% block conditional %}
<style>
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
</style>
<div class="example-wrapper">
<h1>Hello {{ controller_name }}! ✅</h1>
This friendly message is coming from:
<ul>
<li>Your controller at <code>src/Controller/DefaultController.php</code></li>
<li>Your template at <code>templates/default/index.html.twig</code></li>
</ul>
</div>
{% endblock %}
{% if app.user %}
{% block protected_body %}
{{ block('conditional') }}
{% endblock %}
{% else %}
{% block body %}
{{ block('conditional') }}
{% endblock %}
{% endif %}

Finally, I am sure that it is not possible. Maybe a limitation of twig.
So, I have added that condition in controller and render a template or other depending on the user.
Inside both templates, I added an include to a common template.
Regards,
Jaime

You need to place your if inside the block, because conditionals blocks are not a thing in twig
{% block protected_body %}
{% if app.user %}
{{ block('conditional') }}
{% endif %}
{% endblock %}
{% block body %}
{% if not app.user %}
{{ block('conditional') }}
{% endif %}
{% endblock %}

Related

twig attrbutes.addclass nesting issue

Apologies if this has been asked before, but I'm on my first week working with Drupal and Twig.
I have the following code:
{%
set container_classes = [
'paragraph',
'paragraph--type--' ~ paragraph.bundle|clean_class,
view_mode ? 'paragraph--view-mode--' ~ view_mode|clean_class,
not paragraph.isPublished() ? 'paragraph--unpublished',
'container'
]
%}
{% set image_classes = [
'col-12'
]
%}
{% block paragraph %}
{% block content %}
<div{{ attributes.addClass(container_classes) }}>
<div class='row'>
<div{{ attributes.addClass(image_classes) }} data-type='image'>
{{ content.field_two_column_image }}
</div>
<div class='col-12 col-lg-auto' data-type='copy'>
{{ content.field_two_column_copy }}
</div>
</div?>
</div>
{% endblock %}
{% endblock paragraph %}
My issue is the nested attributes.addClass. When I look at the HTML, I'm also seeing the container_classes classes, which is not what I'm looking for.
So how can I separate the two?
You can Create Attributes in Twig.
Something like this should work.
{# attributes for container #}
{% set container_attributes = create_attribute() %}
{%
set container_classes = [
'paragraph',
'paragraph--type--' ~ paragraph.bundle|clean_class,
view_mode ? 'paragraph--view-mode--' ~ view_mode|clean_class,
not paragraph.isPublished() ? 'paragraph--unpublished',
'container'
]
%}
{% set container_attributes = container_attributes.addClass(container_classes) %}
{# attributes for image #}
{% set image_attributes = create_attribute() %}
{% set image_classes = [
'col-12'
]
%}
{% set image_attributes = image_attributes.addClass(image_classes) %}
{% block paragraph %}
{% block content %}
<div{{ container_attributes }}>
<div class='row'>
<div{{ image_attributes }} data-type='image'>
{{ content.field_two_column_image }}
</div>
<div class='col-12 col-lg-auto' data-type='copy'>
{{ content.field_two_column_copy }}
</div>
</div?>
</div>
{% endblock %}
{% endblock paragraph %}

How to reduce duplication in Twig template

I have an if/else condition in a twig template which switches the out tag of a block of code, however the inner block is the same. Is there a way to reduce the duplication without creating a separate file?
This is what I have at the moment:
{% if condition %}
<a href="">
{{ content }}
</a>
{% else %}
<span>
{{ content }}
</span>
{% endif %}
I was hoping to do something such as:
{% if condition %}
<a href="">
{% include mycontent %}
</a>
{% else %}
<span>
{% include mycontent %}
</span>
{% endif %}
{% mycontent %}
{{ content }}
{% endmycontent %}
Is such a thing possible?
If you don't want to use extra files you could use macro's :
{% import _self as macro %}
{% macro foo(content) %}
{{ content }}
{% endmacro %}
{% for condition in [0, 1, 0, 1, ] %}
{% if condition %}
{{ macro.foo('Bar') }}
{% else %}
<span>{{ macro.foo('Bar') }}</span>
{% endif %}
{% endfor %}
fiddle
What you want to do has to be done using the normal syntax. an extra file. and include this file.
But if u want to do this without extra file. use the {% set variablecontent = "put content here" %} and then in your "{% mycontent %}" part u put {{ variablecontent }}
hope this helps

Twig embed block not working when its within a loop?

I need to place a twig template into my page and place another twig template inside it.
In page.twig:
{% embed "parent.twig" %}
{% block something %}
{% include "child.twig" %}
{% endblock %}
{% endembed %}
In parent.twig:
{% set array = ['', '', '']
%}
<div class="parent">
{% for i in array %}
<div class="parent__item">
{% block cardBoard %}
{% endblock %}
</div>
{% endfor %}
</div>
The problem is that the block doesn't work when its within a loop. I can edit page.twig all I like but I would rather not change parent.twig if possible as its consumed by other applications.
Why do you put a block inside a for loop ? You can't have 2 blocks defined with the same name.
In your case it will try to put this in your template 3 times :
<div class="parent__item">
{% block cardBoard %}
{% endblock %}
</div>
This will create a 500 server error :
The block 'cardBoard' has already been defined line '' in :parent.twig at line ''.
If you really want to have content depending on the values in your array, put the block opening and closing outside the for loop.
Like this for example :
{% set array = ['', '', '']%}
<div class="parent__item">
{% block cardBoards %}
{% for i in array %}
<div class="cardBoard{{ i }}>
</div>
{% endfor %}
{% endblock %}
</div>

Navigation link works on mobile but not on desktop

i have this website http://sds-test.nowcommu.myhostpoint.ch/de (please use the "de" at the end) and the last link of the navigation "RECHENZENTRUM" does not works on desktop but works on mobile. How can i solve it? This is the twig code:
{% extends 'partials/base.html.twig' %}
{% set show_onpage_menu = header.onpage_menu == true or header.onpage_menu is null %}
{% macro pageLinkName(text) %}{{ text|lower|replace({' ':'_'}) }}{% endmacro %}
{% block javascripts %}
{% if show_onpage_menu %}
{% do assets.add('theme://js/singlePageNav.min.js') %}
{% endif %}
{{ parent() }}
{% endblock %}
{% block bottom %}
{{ parent() }}
{% if show_onpage_menu %}
<script>
// singlePageNav initialization & configuration
$('#navbar').singlePageNav({
offset: $('#header').outerHeight(),
filter: ':not(.external)',
updateHash: true,
currentClass: 'active'
});
</script>
{% endif %}
{% endblock %}
{% block header_navigation %}
{% if show_onpage_menu %}
<ul class="navigation">
{% for module in page.collection() %}
{% set current_module = (module.active or module.activeChild) ? 'active' : '' %}
<li class="{{ current_module }}">{{ module.menu }}</li>
{% endfor %}
{% set datacenter_page = page.find('/services/datacenter') %}
<li>{{ datacenter_page.menu() }}</li>
</ul>
{% else %}
{{ parent() }}
{% endif %}
{% endblock %}
{% block content %}
{{ page.content }}
{% for module in page.collection() %}
<div id="{{ _self.pageLinkName(module.menu) }}"></div>
{{ module.content }}
{% endfor %}
{% endblock %}
The 'rechenzentrum' link is rendered correctly, and copying the link location via right click gives a correct URL that opens a seemingly correct page. So the template rendering is fine.
The link has two onclick handlers attached to it, though. Probably one of them fails and thus prevents navigation. (The JS is minified so I did not try to debug it.)

Pass Block through multiple Templates

I am trying to set up some common templates, that I want to use throughout my site.
Starting with a template in order to render Users. I have devided this into two different subtemplates:
users.html.twig (Template in order to show a table of Users)
user.html.twig (Template to render a single User)
Depending on the Controller this subtemplates are "included" I may want to add some buttons for each user.
Lets assume I have an action where I can search for users. This Action has the template search.html.twig
Now I want to include within my search.html.twig the users.html.twig which itself includes user.html.twig. The tricky part is, I want to define in search.html.twig a single block that is rendered in user.html.twig. I tried it with embed, but unfortunately it renders nothing:
search.html.twig
{% embed 'StregoUserBundle:Entity:users.html.twig' with {'users': results, 'perRow' : 3} %}
{% block user_additional %}
TOOOOOOOOOOOOP
{% endblock user_additional %}
{% endembed %}
users.html.twig
{% block user_table %}
{% for user in users %}
<div >
{% embed 'StregoUserBundle:Entity:user.html.twig' with {'user': user} %}
{% block user_additional %}
{{ parent()}}
{% endblock user_additional %}
{% endembed %}
</div>
{% endfor %}
{% endblock user_table %}
user.html.twig
{% block single_user %}
<div class="people-list">
<a href="{{ path('profile_show', { 'username': user.username }) }}">
<img src="{{ user.profilePic | imagine_filter('profile_thumb') }}" alt="{{ user.username }}" class="img-polaroid">
</a>
<h3>{{ user.username }}</h3>
<h3><small>{{ user.firstName }} {{ user.lastName }}</small></h3>
{% block user_additional %}
{% endblock user_additional %}
</div>
{% endblock single_user %}
I have tried several combinations of {{ block('XXX')}}, includes, embed, use etc... but did not find a solution.
Should't
{% endembed %}
be
{% embeded %}

Resources