symfony twig extends: 'only extend if' - symfony

In twig there is the 'extends' tag, as found here; http://twig.sensiolabs.org/doc/tags/extends.html#conditional-inheritance
Now what I wanna do is something along the lines of the following example from that page:
{% extends standalone ? "minimum.html" : "base.html" %}
But rather than having 2 templates to extend from, I just want to extend from a template if a specific condition is met.
Now I've tried things such as:
{% extends boolean ? "template.html.twig" : "" %}
and:
{% if boolean %}
{% extends "template.html.twig" %}
{% endif %}
but the former gives an error saying it cannot find a template (since "" obviously isnt a valid path), and the latter just doesn't appear to do anything at all (or rather, it loads for a while and ends up not showing anything)
I've tried some other approaches, but couldn't come up with anything, so figured I'd ask here if I might be missing something.
Thanks in advance for any replies :)
EDIT: To sum up my intent; I am wondering if I can tell my template to only extend if a certain condition is met, and otherwise skip the extend step. (if condition then extend else do nothing)

Twig files are generated into PHP classes.
The extends tag should be the first tag in the template, as:
the {% extends %} tag will be converted to the PHP extends so the child template will inherit from the parent template.
the {% if %} tag is generated as a PHP if, inside a method of the template class, so you can't use {% if %} to extend some class or not.
Anyway, you can extends a variable coming from your context, so you should put your condition in the controller.
if ($boolean) {
$template = 'hello.twig';
} else {
$template = 'world.twig';
}
$this->render("MyBundle:MyFeature:child.html.twig", array('template' => $template);
And then in child.html.twig:
{% extends template %}

I came with this hack: added empty layout only with content block. Seems to be working :) I can pass variable from controller and page is loaded with or without layout.
<!-- base.html.twig -->
<head>
...stuff...
</head>
<body>
{% block content %}{% endblock %}
</body>
<!-- empty.html.twig -->
{% block content %}{% endblock %}
<!-- some_page.html.twig -->
{% extends boolean ? 'base.html.twig' : 'empty.html.twig' %}
{% block content %}
Now this is my real content
{% endblock %}

In pure twig language, it could be something like this :
{% if app.request.pathinfo starts with '/react' %}
{% set extendPath = "::react_base.html.twig" %}
{% else %}
{% set extendPath = "CoreBundle::layout.html.twig" %}
{% endif %}
{% extends extendPath %}

Related

extends in symfony from multiple children

I have a base.html.twig with the basic html.
In the 'base' I have a {% block body %}{% endblock %} and a {% block javascript %}{% endblock %}
I call a 'form.html.twig' file from the Controller and the template extends the base.html.twig.
The 'form' contains the <form> and </form> tags and can contain a random numbers of sub templates/form elements:
'{% block body %}
{% for template in templates %}
{% embed template %}{% endembed %}
{% endfor %}
{% endblock %}'
The 'template' is perhaps a customer.html.twig, confirm.html.twig, vehicle.html.twig etc. etc. and they all have {% block body %} and {% block javascript %} - now for the question:
The content in the template files aren't moved to the blocks body/javascript. How do I get twig/symfony to move the content in the template files to the respective areas in the 'base.html.twig'?
Thank you for your time.
You want to use the use twig tag instead of the embed tag like this
{% use template %}
See more info here:
http://twig.sensiolabs.org/doc/tags/use.html

Twig: Extend template !only! on condition? Or dynamicly extend on PHP-side

I've got a twig template:
{% extends base %}
{% block content %}
some content
{% endblock %}
Is there any way to render it without "extending" any template?
If i leave the "base" unset, an error appears.
Something like
{% if base is defined %}
{% extends base %}
{% endif %}
does not work, as far as i know.
Or another option might be, if there is a way to dynamicly define a parent on the php side, like u can do in Smarty:
$smarty->display('extends:layout.tpl|myproject.tpl|mypage.tpl');
Thx!
You can conditionally set template:
{% extends base is defined ? 'main.html.twig' : 'empty.html.twig' %}

Override form_end block for one form

I want to override form_end block but only for one form. My blocks are loaded globally in my config.yml file. For example when i want to override form_row for one field i can make block like this -> formName.field.row.
I was trying to make something like this:
{% block formName_form_end %}
my Code
{% endblock %}
but It doesn't work. Maybe it's just not possible to override form_end using form_name ? I mean that i can only override form_end, but in my case it will affect all forms.
You need form themeing.
{% form_theme form _self %}
{% block form_end %}
my Code
{% endblock %}
{# Rest of template #}
As noted in the documentation, use of _self tells Twig to look for block overrides within the current template file.

Problems with include

i have a lot of time programming in PHP, but im doing my first steps in Symfony.
Im try write Twigg templates, i have a public template in app/Resources/view/public.html.twig.
This file contains: http://pastebin.com/T1KGMfXL.
Now, in CloudBundle, have a base.html.twig:
{% extends '::public.html.twig' %}
{% block main %}
<div class="login_page">
<div class="login_box">
{% block content %} {% endblock %}
</div>
</div>
{% endblock %}
And the content in another twig file. For example, login.html.twig
{% extends 'base.html.twig' %}
{% block content %}
....
{% endblock %}
In the Controller, when an user try http://cloud.man.local/app.php/login:
public function staticAction($sitio)
{
// in this case, $sitio contains "login"
return $this->render("CloudBundle:Default:$sitio.html.twig");
}
So, the problem is that, only shows the footer, not show the content.
Any ideas ?.
You want to override a block which is inside another block, so in your case I think you should try this in the another twig files:
{% block main %}
{{ parent() }}
{% block content %} YOur content {% endblock %}
{% endblock %}
see http://twig.sensiolabs.org/doc/functions/parent.html
Hope it's helpful.
Best regard.

How to check if a block exists in a twig template - Symfony2

Imagine I have something like this in my twig template
{% block posLeft %}
-----
{%endblock%}
Is there any way to check for existance of the posLeft block without calling to:
block("posLeft")
And check the return value of the posBlock to varify the existance. I am a newbie in Symfony2 + Twig.
You can solve it like this, if you want to display a certain block only if it has content. Hope, this is what you're looking for.
Example index.html.twig
{% set _block = block('dynamic') %}
{% if _block is not empty %}
{{ _block|raw }}
{% endif %}
Example part.html.twig
{% extends "index.html.twig" %}
{% block dynamic %}
Block content goes here.
{% endblock %}
You can do it like this:
{% if block('posLeft') %}
...
{% endif %}
But it is not efficient if you need output of rendered block.
So if you will need block output you should assign it to variable in the first place
and then do assertions
The other answers here do not work for twig 2.1 (I've not tested on ~2.0), so here's a small update:
{% if block('dynamic') is defined %}
{{ block('dynamic')|raw }}
{% endif %}
Note that the line to render the block is not:
{% block dynamic %}
{# this wont work #}
{% endblock %}
This wont work because the block will be rendered during compile, and so the test will return true that it exists (as its tested at runtime). So you need to render the block with {{ block('dynamic')|raw }} instead as this doesn't actually define the block in the template.
First check, which Twig version you are using inside your Symfony project, because the answers here are only for Twig 1.
If you are using Twig 2 you are lucky. According to the Twig documentation, you can use the defined test to check if the block exists in the current template context.
{% if block("dynamic") is defined %}
...
{% endif %}
I have written a little TwigExtension to check if the block gets called inside the if statement and it seems like Twig only really checks if the block exists and does not call it.
The link to the docs: https://twig.symfony.com/doc/2.x/functions/block.html
If you are using Twig 1, the old answer at https://stackoverflow.com/a/13806784/6458657 is still correct.
Twig 2.x
{{ (block("posLeft")) ?? '' }}
If you want to display a block if it's defined or not in one line. Might be a little kludgy but satisfies my needs without a bunch of if..then logic.
Just want to provide another example which worked for me.
<body
{% if block('ngapp') is not empty %}ng-app="{% block ngapp %}{% endblock %}"{% endif %}
>
This allows me in child templates declare {% block ngapp 'myApp' %} and have it displayed within parent.
This was needed because on some pages I was bootstrapping Angular manually via (angular.bootstrap('moduleName', rootElement)) and Angular does not like empty ng-app='' directive and breaks in weird ways.
The accepted answer didn't work for me in Twig 3.3.10, throwing an error that the block wasn't defined.
To solve this and define a block whose contents are conditionally wrapped in a container, only if any block content is set, this worked:
Parent template with block definition and wrapper element
{# parent.twig #}
<h1>Hello. I am the parent.</h1>
{% if block('sidebar') is not empty %}
<div class="sidebar-container">
{% block sidebar %}{% endblock %}
</div>
{% endif %}
Child template setting block content
{% extends 'parent.twig' %}
{% block sidebar %}
Sidebar content from child template
{% endblock %}
Output – block content inside wrapper:
<h1>Hello. I am the parent.</h1>
<div class="sidebar-container">
Sidebar content from child template
</div>
Child template not setting block content
{% extends 'parent.twig' %}
{# sidebar block not set in this one... #}
Output – no empty wrapper element:
<h1>Hello. I am the parent.</h1>

Resources