Twig: Override elements with embed - php

I have the following template structure and I want to override a block with embed:
base.html.twig
<!DOCTYPE>
<html>
<head></head>
<body>
{% embed 'header.html.twig' %}
{% block content %}{% endblock %}
{% endembed %}
</body>
</html>
header.html.twig
{% block content %}{% endblock %}
page.html.twig
{% extends 'base.html.twig' %}
{% block content %}
<p>Some content</p>
{% endblock %}
If I load the page.html.twig with my controller now I thought it should display "Some content" but it doesn't work. Does anyone have an idea what I did wrong?

"The embed tag combines the behaviour of include and extends. It allows you to include another template's contents, just like include does. But it also allows you to override any block defined inside the included template, like when extending a template."
twig document about embed block
You can use import or include. I recommend include fot this state

Related

Symfony, Twig. An advanced way to connect styles and scripts for a page [duplicate]

I would like to inject inside the styles and scripts blocks in my layout new values, but from the embed block.
Of course it throws the error Calling "parent" outside a block is forbidden..
Is there any workaround ?
layout.html.twig:
<!DOCTYPE html>
<html>
<head>
{% block style %}
<link rel="stylesheet" href="foo.css">
{% endblock %}
</head>
<body>
{% block content "" %}
{% block scripts %}
<script src="foo.js"></script>
{% endblock %}
</body>
</html>
list.html.twig:
{% extends 'layout.html.twig' %}
{% block content %}
{% embed datatable.html.twig %}
{% block tbody %}
<tr>
<td>my awesome table</td>
</tr>
{% endblock %}
{% endembed %}
{% endblock %}
datatable.html.twig:
<table id="myDatatable">
<tbody>
{% block tbody "" %}
</tbody>
</table>
{% block styles %}
{{ parent() }}
<link rel="stylesheet" href="dataTables.css">
{% endblock %}
{% block scripts %}
{{ parent() }}
<script src="dataTables.js"></script>
{% endblock %}
(And I cant/wont use the blocks scripts and styles inside the list.html.twig. They are part of the datatable template, it will not make any sens to define theme in the list.html.twig.).
And sadly I cant use use because this function does not support dynamics properties, only strings.
From the doc :
Because use statements are resolved independently of the context passed to the template, the template reference cannot be an expression.
As said in the comment, includes/embeds can't alter blocks from their includer.
That said there is an extension available that could solve your problem.
This Deferred Twig Extension can be found here
Basically the node postpones the execution of a said block.
This way you can create a variable that holds all of your javascript links and output them. This can be seen in the advanced example found on the github.
credits to Eugene Leonovich for making this extension

Two templates showed

I'm using FOSUserBundle on my Symfony4 project, and I overrode all bundle templates, and place them on my templates folder.
I have my base.html.twig file, is the main page template that contains initial HTML script for all stylesheets and javascript files. On the body I added the content block:
<body>
{% block content %}{% endblock content %}
</body>
Then, on my login template, I extended the main template and added the fos_user_content block:
{% extends 'bundles/landing.html.twig' %}
{% block content %}
{% block fos_user_content %}
{% endblock content %}
And for the moment everything is ok. The login form is displayed well. But when I log into this form, the system switched me to the Profile page. The problem, is that, the profile page template is showed and the login template too.
Both the templates are used.
On the profile template, I extended the main template too + added the same block content, except the fos_user_content block.
You missed an {% endblock fos_user_content %} tag
{% extends 'bundles/landing.html.twig' %}
{% block content %}
{% block fos_user_content %}{% endblock fos_user_content %}
{% endblock content %}

render option twice in base.html.twig

I got base.html.twig file inside i wanna render two controller
Is that is possible ?
</head>
<body>
{% block header %}{{ render(controller('App\\Controller\\FrontController::front_header')) }}{% endblock %}
{% block content %}{% endblock %}
{% block footer %}{{ render(controller('App\\Controller\\FrontController::front_footer')) }}{% endblock %}
</body>
{% block javascripts %}{% endblock %}
or what way is the best to handle something like that ?
becouse frontcontroller render anothe index.html.twig which will get some stuff to block content and i wanna have this block content between two another controllers.
why not simply use Twig include for your header and your footer?

Create event in symfony2 to render a twig file

I'm new to symfony2 and I'm looking for solution to create an event that render a twig file.
Assume we have a base template
<!DOCTYPE html>
<html>
<head>
{% block meta %}{% endblock %}
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}{% endblock %}
</head>
<body data-cachetime="{{ cacheTimeStamp() }}">
{% block header %}{% endblock %}
<div id="content">
<div class="container">
{% block content %}{% endblock %}
</div>
</div>
{% block footer %}{% endblock %}
{% block version %}{% endblock %}
{% block javascripts %}{% endblock %}
{% block trackers %}{% endblock %}
</body>
</html>
As you can see, I've a "version" block. I've created an VersionBundle which read the version from a file. The version twig template
{% block version %}
<div id="version"><p>Version: {{ versionString() }}</p></div>
{% endblock %}
calls an "ViewHelper" (i came from Zend ;-)) which calls the function from VersionBundle. But now the tricky part:
The VerionBundle is only registered for 'dev' and 'test' Environment in the AppKernel.
Thats why i create the 'version' block instead of calling the ViewHelper directly in the base twig file.
But i don't know how to create an event to render the version twig template first so the data will passed to the base twig.
I would maybe change the way you try to do it, using more Symfony features and avoiding defining Zend like "helpers". It's a good rule of thumb to keep Twig as minimal as it can be, just rendering view from data the templates receive.
First, define the version variable in parameters_dev.yml and parameters_test.yml files (in app/config). Example:
parameters:
version: 32
Define it as version: ~ in parameters.yml.
Make this variable available in all Twig templates in the app/config/config.yml file:
twig:
globals:
version: %version%
Then, in your version block definition, do the following:
{% block version %}
{% if version is not null %}
<div id="version"><p>Version: {{ version }}</p></div>
{% endif %}
{% endblock %}
Hope it helps!

Twig templates, inheritances and block usage

I've created three templates using Twig. The first one has block A defined in it, the second one extends from the first one, but includes a third template which sets the content of block A.
When loading, through the browser, the url which renders b.html.twig, the content in block A (defined by the 3th template) is not positioned block _A is defined.
Example:
<!-- base.html.twig -->
{% block _css '' %}
{% block _header '' %}
{% block _content '' %}
{% block _footer '' %}
{% block _js '' %}
<!-- layout.html.twig -->
<!-- header and footer are placed in the raight zone -->
{% extends ::base.html.twig %}
{% block _header %}
{% render "MyBundleBundle:Header:header" %}
{% endblock %}
{% block _footer %}
{% render "MyBundleBundle:Footer:footer" %}
{% endblock %}
<!-- my_template.html.twig -->
<!-- content is also placed in the right zone but css and js blocks in the included template are not placed where declared in base.html.twig -->
{% extends MyBundleBundle::layout.html.twig %}
{% block _content %}
SOME_CONTENT
{% include MyBundleBundle::my_included_template.html.twig %}
{% endblock %}
<!-- my_included_template.html.twig -->
{% block _css %}
<link.......................>
{% endblock %}
{% block _js %}
<script..................>
{% endblock %}
MORE CONTENT BELONGING TO THE INCLUDED TEMPLATE
What i expect here is, _css blocks content to appear on top of the page and _js block content at the bottom, but that's not happening. I hope you can see where i'm going wrong, thanks!
The include tag does not work the way you think/hope it does. It simply includes the file into the current context. Which means you can't reference blocks. You can only reference blocks in a template that has the extends tag at the top of the file.
You're going to have to restructure the way you've designed your template to make this work for you. Instead of including my_included_template.html.twig you should possibly just render that template directly in your controller. That way it'll have full access to any inherited blocks.

Categories