is it possible in symfony2 to extend 2 templates? - symfony

I'm thinking to organize my base layout in symfony2 containing only 3 blocks: header, content, and footer. And I want to have one template for each block. The "content" template will be a template that will be empty, showing only the templates for every section, following the "3 levels" directives.
But I don't know how to include the header and footer template. I've done it creating "by pass" templates, so, for example, content extends footer, footer extends header, and header extends base, but it looks very bad.
Thanks.

you can use the embed tag, that 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,
but version 1.8 is required
The embed tag

You can't extend more than one template in Twig, it is illogical anyway.
You should use include, which is a bit different.
The common way is to have one base template, which will be extended by all the other ones, except the header and the footer that will be included in it.
base.html.twig:
...
<body>
{% include '::header.html.twig' %}
{% block body %}{% endblock %}
{% include '::footer.html.twig' %}
</body>
...
In the other templates, your bundles' views for example:
{% extends '::base.html.twig' %}
{% block body %}
Hello world!
{% endblock %}

Related

How can i only get the body contents of easyAdmin bundle twigs

I want the functionality of EasyAdmin Bundle but i just want the body tag cause i have my own template and i can't seem to be able to extract only the contents of the body tag.
i tried the checking out the code but it keeps referencing other twigs
i just want what's inside the body block in html and css
{% extends 'baseback.html.twig' %}
{% block body %}
{% endblock %}
this is what i need from the bundle code."
If you look at the EasyAdmin source code:
https://github.com/EasyCorp/EasyAdminBundle/blob/master/src/Resources/views/default/layout.html.twig
You can see that body block contains everything including menus and stuff; where content block is what you want.
Now in the documentation:
https://symfony.com/doc/master/bundles/EasyAdminBundle/book/edit-new-configuration.html#overriding-the-default-templates-using-symfony-s-mechanism
You can override the above layout.html.twig in your own project to only render what you want.

How to modify endblock content in symfony

I want to modify the content of the end block in the symfony. When I did inspect element at that time it is showing in model-footer. How can I modify footer content.
I want to change name from save order to save
The question is not clear but I think I know what you mean ...
Normally you have a block {% block footer%} {% endblock%} in your base.html.twig. To add content, go to the specified view by adding ...
{% block footer%}
// Your HTML Content
{% endblock%}

Symfony Form Theme extend inline

I extend FosUserBundle register form like this:
{% extends "#App/base.html.twig" %}
{% form_theme form 'bootstrap_3_horizontal_layout.html.twig' %}
{% block form_label_class -%}
col-md-8
{%- endblock form_label_class %}
Unfortunately the block form_label_class which is from bootstrap_3_horizontal_layout.html.twig is not extending there.
I want now in my form to use label as col-md-8 (instead the default col-sm-2) but then in another form maybe want to use col-md-6 and so on.
Is there an easy way to do it inline in every from instead create extends for each col-md-XX which is really not very convenient at all.
Thanks a lot!
You need to tell Symfony to include your current template as a form theme:
{% form_theme form with [
'bootstrap_3_horizontal_layout.html.twig',
_self,
] %}
Otherwise, it doesn't know to look in the current template for form theme blocks.
You can also use this to include other templates with form blocks as well. This is helpful if you have multiple templates that re-use the same form blocks; you can refactor them all into one template and reference it everywhere it's needed.

Twig the same block in different included files

I have problem with included files. In my layout.html.twig I have scripts.js at the end body section before {% block script %}{% endblock %}. When file extending layout and use script block, its ok, but when use this block and include file whose use the same block, then is problem. Rendered page has all javascripts, but in different places.
For example:
page.html.twig
...
There is page.html.twig
{% include 'file.html.twig' with {'something': 'something'} %}
After include file.html.twig
..
{% block script %}
<script src="file1.js"></script>
{% endblock %}
file.html.twig
There is file.html.twig
{% block script %}
<script src="file2.js"></script>
{% endblock %}
Then rendered page look like this:
There is page.html.twig
There is file.html.twig
<script src="file2.js"></script>
After include file.html.twig
<script src="file1.js"></script>
I want have all javascript files in one place, one by one.
I think you should try to 'embed' instead of 'include'.
http://twig.sensiolabs.org/doc/tags/embed.html
With embedded, you can choose blocks to include.
Ps : If you override a block, you can get the parent block content in using parent() :
{% block script %}
{{ parent() }}
{% endblock script %}
The {% block %} tag and the inheritance system work only with layouts and {% extends %}. It is not meant to be used with includes, so the script block in your included file.html.twig does not merge with page.html.twig.
One solution would be to set a an argument to you included file.
file.html.twig
{% if get == 'content' %}
There is file.html.twig
{% endif %}
{% if get == 'script' %}
<script src="file2.js"></script>
{% endif %}
page.html.twig
...
There is page.html.twig
{% include 'file.html.twig' with {'something': 'something', 'get': 'content'} %}
After include file.html.twig
..
{% block script %}
<script src="file1.js"></script>
{% include 'file.html.twig' with {'something': 'something', 'get': 'script'} %}
{% endblock %}
You will need to conform to a standard practice when dealing with included templates and inheritance (you can invent your own standard).
Try to compartmentalize your includes, I usually have a directory called 'partials' for includes, and 'fragments' for renders. Each one belonging to a single collection of controller views.
One way I dealt with a similar problem to what you are having was to use a base template which covered the requirements of a specific set of views, each view template would extend it. It may be somewhat wasteful to include the javascripts and stylesheets for the entire collection of views for a specific controller, but it is a) more efficient that including all assets everywhere and, b) I manage the view specific assets under a single base template.
So long as the views have a dependency on that base template the structure wouldn't break.
Think of Twig templates as PHP classes (they compile to classes anyway). A class can inherit from one chain of parents. What you are trying to do is treat two sub-classes as a single child of a super class, overriding the same method at the same time. Simply can't be done. An include is closer to a child property, with is own rules and properties. The included template is less dependent on the includer than vice-versa, so it is impossible for it to inherit from it conventionally.

Twig: render Symfony2 controllers which extend blocks in the parent template

Say I'm having a base template like this:
// Default/index.html.twig
{% block javascripts %}
<script>//some script</script>
{% endblock %}
<div>
{{ render(controller(MyControllerBundle:Default:header)) }}
</div>
{{ text }}
<div>
{{ render(controller(MyControllerBundle:Default:footer)) }}
</div>
And this renders controllers having these templates:
// Default/header.html.twig
Header content
{% block javascripts %}
<script>//some additional scripts from the header</script>
{% endblock %}
and
// Default/footer.html.twig
Footer content
{% block javascripts %}
<script>//some additional scripts from the footer</script>
{% endblock %}
Is it possible somehow to use the javascripts block from the rendered sub controllers in the parent template?
I want to have all javascripts cumulated in one place.
Rendering from bottom up with extending is no option here because the template consists of
multiple blocks that are rendered by different controllers.
Is this possible somehow? Or is there a better approach to this?
Anything is possible however design-wise it might not be a good idea.
The render tag is really useful when it comes down to scaling and it used as a way to isolate a request. Each render call is considered as a sub-request and a cache strategy can be applied to it.
I'd highly advise you to read this documentation about HTTP caching and especially the part that talks about Edge Side Includes (or ESI).
When you use the render tag, think of it as a module you want to include in multiple pages and eventually cache.
You shouldn't interact with the master request because the sub request is isolated for caching (depending on the place you embed the render tag, the master request will be different which means you might get some unexpected results).
First of all, I'd create a layout template that every other pages extends. The layout template will declare all the basic blocks (javascript, css, footer, header, <head>, <body> - you can abstract in more templates if you want).
If you have logic for your footer or header split them into Twig functions (or filters) and handle the logic in Twig but keep it light (if it's too complicated or too spaghetti that means there is another way).
Avoid having multiple Javascript or CSS files per page. If you have some css or javascript that appears on some pages but not all of them it's still probably a good idea to merge them into one file (less DNS calls on the client side and once it's cached it will be faster to load the page).
If you have a administrator.js kind-of file, then you could include it as a separate file but if most requests come from administrators then you might want to include it with all the other files.
If you didn't know you can combine assets (js or css) into one file: more info in the Symfony documentation.
I didn't answer your "how" question because I'd strongly advise you to not implement such a system however I believe I've shared good guidelines to make an informed decision.
when extending / rendering other content in TWIG you can call the parent block: http://twig.sensiolabs.org/doc/functions/parent.html
this means that you can leave default as it is and inside header / footer define
{% block javascripts %}
{{ parent() }}
{# other scripts #}
{% endblock javascripts %}
I would suggest that you have different block name for the footer - that way you can include scripts outside of the header.
Also, it might be best to keeps scripts in one place - that way you can use assetic rewrite's later down the line : http://symfony.com/doc/current/cookbook/assetic/asset_management.html#including-javascript-files
exactly what #Pazi says in the comment: Do you need a controller? It looks pretty simple to just include the template by itself, without using a controller.
You might use the include tag to include the subtemplates.
{% include 'MyControllerBundle:Default:header.html.twig' %}
For reusing the javascript block from the rendered sub controllers, you could create a base template that contains the javascripts block. Then extend that base template file in your header and footer. Or just including the base template in them should work, too.

Resources