Can I fliter out a Twig block from one page to another? - php

Hope someone can please advise.
I'm working on a theme for a CMS. I have one twig-based page as the theme template, so obviously all of the Twig blocks for the different types of pages are in the one document.
The CMS has two types of pages that can be created and viewed via the page builder.
At the moment, all of the Twig blocks appear in page A as well as page B from the font-end.
Is it possible for me to write some Twig code that will enable to me to display a Twig block on page A, but not on page B?
I understand I need some sort of filter, but do I filter by url, or is there a better way?
Appreciate any help you can give me.

To prevent a block from an extended template from showing you can override the block
main.twig
{% block foo %}
Foo
{% endblock %}
{% block bar %}
Bar
{% endblock %}
child.twig
{% extends "main.twig" %}
{% block foo %}{% endblock %}
The snippet above will just display Bar
To take it a step further, you can override a block and still let the original block of the extended template be executed, by using the function {{ parent() }}
child.twig
{% extends "main.twig" %}
{% block foo %}
Lorem Ipsum<br />
{{ parent() }}
{% endblock %}
This will output
Lorem Ipsum<br />
Foo
Bar
With this explained, you can wrap the function call parent() in any condition you like, thus controlling which block to show/hide
{% extends "main.twig" %}
{% block foo %}
{% if conditionA == true %}
{{ parent() }}
{% endif %}
{% endblock %}
{% block bar %}
{% if conditionB == true %}
{{ parent() }}
{% endif %}
{% endblock %}
demo

Related

Print debug stack trace (within block)

Trying to extend a formbuilder plugin for Pimcore (https://github.com/dachcom-digital/pimcore-formbuilder) I am trying to modify the output of input/select fields in order to be compatible with MD Bootstrap syntax.
Therefore I override /FormBuilderBundle/Form/Theme/bootstrap_4_layout.html.twig. The shortened content of this file is like this:
{% extends 'bootstrap_4_layout.html.twig' %}
{% use '#FormBuilder/Form/Theme/Type/dynamic_multi_file.html.twig' %}
{% use '#FormBuilder/Form/Theme/Type/html_tag.html.twig' %}
{% use '#FormBuilder/Form/Theme/Type/snippet.html.twig' %}
{% use '#FormBuilder/Form/Theme/Type/container.html.twig' %}
{% block form_row -%}
{% set form_row_class = attr['data-template'] is defined ? attr['data-template'] : 'col-12' %}
{% if form.vars.is_form_builder_container_block is defined %}
{% set form_row_class = 'formbuilder-container-block' %}
{% endif %}
<div class="formbuilder-row md-form {{ form_row_class }}">
{{ parent() }}
</div>
{%- endblock form_row %}
The problem is that there is no other file called bootstrap_4_layout.html.twig (except in the macros folder) and the template can not extend itself. I want to find out what the parent() function is doing here in order to alter the output (https://twig.symfony.com/doc/3.x/functions/parent.html).
As I still did not find the template which is extended I would like to print the parent() functions' stack trace in order to know which files are involved. Is there any possibility to do this with Twig (maybe with a Twig Extension)?

How can I pass variable from parent template to child template in Twig?

I'm working with Symfony and Twig and I can't find solution for the next problem:
in my parent template (index.html.twig) I have such code:
<noscript>
{% block noscript %}
<div class="alert alert-warning">
<strong>{% block notice %}{{ notice_js_disabled }}{% endblock %} </strong>
{% block message %}{{ js_disabled }}{% endblock %}
</div>
{% endblock %}
</noscript>
I have child template (category.html.twig) which extends index.html.twig template.
Can I pass value of {{ notice_js_disabled }} var from index template to category template?
notice_js_disabled is returned from my Symfony indexAction controller.
UPD:
The solution for my problem I founded, next:
I have made base templae, called main.html.twig, where I'm rendering element from the controller:
{% block header %}
{{ render(controller('StoreBundle:Header:index')) }}
{% endblock %}
Then, on my index.html.twig file, I made next things:
{% extends 'Store/tpl/main.html.twig' %}
{% block title %}{{ title }}{% endblock %}
{% block content %}
<p class="currentPage" hidden>home</p>
{{ parent() }}
{% endblock %}
I'm not sure is it correct solution, but it's work:)
The only way in Twig you can pass some variable to a child template is by the include tag.
{# template.html will have access to the variables from the current context and the additional ones provided #}
{% include 'template.html' with {'foo': 'bar'} %}
{% set vars = {'foo': 'bar'} %}
{% include 'template.html' with vars %}
However in this way you are not extending some parent template from the child, but you are doing the other way around: you are placing a submodule into the current template.
There are only a couple of variables which are global in symfony
You can set some custom global variables in configuration like described here
Otherwise you can use some predefined global variables, the app variable. (check it out here)
My personal advice is that you should review your application template logic.
Hope it helps!
What you have to do is the following:
-Create A variable in the parent template
{% set notice_js_disabled = value_received_from_indexAction %}
After the template that you need that value
{{ notice_js_disabled }}
I hope it helps you

Symfony2/Twig - how to set template file contents as variable?

In Symfony 2.8 I've got SharedBundle, where I keep views and other things I share between other bundles, including the whole layout that should be extended by other bundles' views.
That shared layout has some typical blocks, from which sidebar block should be different for different bundles.
Currently I did an ugly workaround:
In SharedBundle sidebar container:
{% if sidebarcontent is defined %}
{{ sidebarcontent|raw }}
{% else %}
SIDEBAR NOT FOUND
{% endif %}
And in other bundles (here: BundleA) in every view that extends the shared main view:
{% extends 'SharedBundle:layout.html.twig' %}
{% block sidebar %}
{% include 'BundleA:_partials:sidebar.html.twig' %}
{% endblock %}
{% set sidebarcontent = block('sidebar') %}
But that doesn't look good, I think. Is there a better way?
I think this is a valid approach. The only simplification I can think of is not using the variable sidebarcontent.
You can use block('sidebar') inside the if statement:
{% if block('sidebar')|length > 0 %}
{{ sidebarcontent|raw }}
{% else %}
SIDEBAR NOT FOUND
{% endif %}
Make sure the block exists before checking it's content, so initialise it with an empty string:
{% block sidebar %}{% endblock %}

Twig Inheritance: get raw resulting template

I'm developing Symfony2 + Twig project. I need to get raw not interpeted template (variables shouldn't be replaced) string in Symfony2 Controller after merging with its parent template.
For example:
parent.html.twig
{% block title %}
Parent Content
{% endblock %}
child.html.twig
{% extends "parent.html.twig" %}
{% block title %}
{{ parent() }}
{{ CHILD_CONTENT }}
{% endblock %}
Desirable result is a string:
Parent Content
{{ CHILD_CONTENT }}
I've heard about source function in 1.15 version, but it doesn't handle inheritance.
Is there any way to get around?
already tried "verbatim"? http://twig.sensiolabs.org/doc/tags/verbatim.html
Your code should look like this:
{% block title %}
{{ parent() }}
{% verbatim %}
{{ CHILD_CONTENT }}
{% endverbatim %}
{% endblock %}
This should solve your problem.

Multiple extension of layout in twig/php

I have a problem figuring out how to solve the following issue with Twig templates
I have a system where two parts wants to change blocks in the layout without know each other. The idea of my templates are
main.twig
<html><body>
{% block a %}{% endblock %}
{% block b %}{% endblock %}
</body></html>
replacea.twig
{% extends "main.twig" %}
{% block a %}hello{% endblock %}
replaceb.twig
{% extends "main.twig" %}
{% block b %}world{% endblock %}
My problem is that I do not know how to achieve this, as the places where I call replacea and replaceb only shares a "viewengine" so I am able to collect all render calls and bulk them.
My first idea to solve this was to extend a variable, say "layout", but then when I call render layout would be replaced with the same in all templates and not with "replacea.twig" in replaceb and with "main.twig" in replacea.
Hope you understand my problem.
You need to use "Use" - pun not intended! :-)
main.twig
<html><body>
{% block a %}{% endblock %}
{% block b %}{% endblock %}
</body></html>
replacea.twig
{% block a %}hello{% endblock %}
replaceb.twig
{% extends "main.twig" %}
{% use "replacea.html" %}
{% block b %}world{% endblock %}
Check out the documentation:
https://twig.symfony.com/doc/tags/use.html

Categories