My Symfony app view layout is a three level hierarchy, such that there is the baseview.html.twig and then the child of that is layout.html.twig and then the child of layout view is X,Y,Z,.... .html.twig. I wanted to pass in a form to the layout.html.twig, however where in my controller should I do this?
Here's some code to make it more clear of the hierarchy. In the bottom base line view I have the following:
{% extends 'AppMainBundle::layout.html.twig' %}
and then in layout.html.twig I have:
{% extends '::base.html.twig' %}
so I wanted to pass in a formView to my layout.html.twig, the question is how??
Use blocks like block content in documentation
For Ex:
{% extends '::base.html.twig' %}
{% block content %}
{{form_widget(form)}}
{% endblock %}
Now content block will be replaced in parent by your block.
Related
Let's say I have the following twig templates:
{% block header %}My header{% endblock %}
{% block middle %}My middle{% endblock %}
{% block footer %}My footer{% endblock %}
In my controller, I render the twig file (with laravel twig bridge, but it would be similar in other frameworks):
public function index() {
$view = view('template.twig');
return $view->render();
}
So is there a way, to manipulate the $view to set for example the block middle to My new middle, within the controller, without touching the template.twig file?
I know, I could create a new child.twig where I do
{% extends "template" %}
{% block middle %}My new middle{% endblock}
but is there a way to do it, without an extra twig file directly form the controller? Something like
$view->setBlock('middle', 'My new middle');
I want to extend my base twig template with some asset bundles and add new assets in child template.
{# main.twig #}
register_asset_bundle('app/assets/AppAsset')
{# child.twig #}
{% extends 'layouts/main.twig' %}
register_asset_bundle('app/assets/NewAsset')
So I got error "A template that extends another one cannot include content outside Twig blocks. Did you forget to put the content inside a {% block %} tag?"
So need I to set each asset to blocks? That is uncomfortable when I use asset bundles. Google have no one solutions for this, what should I do in this situation?
It is required for a child template to have its content strictly in the block tags. The engine substitutes the parent blocks for the blocks defined in the child.
Therefore, your main.twig template should include at least one block, e.g.:
register_asset_bundle('app/assets/AppAsset')
{% block content %}{% endblock %}
So that the child can override it as follows:
{% extends 'layouts/main.twig' %}
{% block content %}
register_asset_bundle('app/assets/NewAsset')
{# More content here #}
{% endblock %}
Whatever you put into the "content" block in the parent template will be replaced with the content of that block defined in the child.
I have two templates:
Fields.html.twig, which includes a child template.
{% block important %}
This block should be renderable from the sub template
{% endblock important %}
{% include 'XButton.html.twig' %}
XButton.html.twig, which needs to render blocks defined in the template that includes it.
block('important')
It seems like an included template isn't able to simply render blocks of whoever included it.
How can the parent template pass the full context to the child, so that the child can access the blocks defined in the parent?
What you're trying to do it's impossible, because the included template has no way to know about blocks defined in other templates...
You'll need to structure your code a bit differently, so that the contents of the block are defined in the parent somehow - you have at least a couple of options:
Using set and include: https://twigfiddle.com/l536np
Fields.html.twig
{% set important %}
You define the child content as a variable in the parent...
{% endset %}
{% include 'XButton.html.twig' %}
XButton.html.twig
{{ important }}
Using embed: https://twigfiddle.com/y9pp6p
Fields.html.twig
{% embed 'XButton.html.twig' %}
{% block important %}
You define the block content in the parent...
{% endblock %}
{% endembed %}
XButton.html.twig
{{ block('important') }}
You can do it with include by passing the parent template name
{% block important %}
This block should be renderable from the sub template
{% endblock important %}
{% include 'XButton.html.twig' with {'parent': _self} %}
And then use it in the include template
{{ block('important', parent) }}
Although this way the content of the block will be rendered twice - once when you define it in the parent, and once again in the child - see https://twigfiddle.com/6t0l6p
I do my first project in Symfony2. I have problem with template. My main twig file is "index.html.twig". It's located in src/Gogs/CMSBundle/Resources/views/Default/index.html.twig
I try to extends main twig file from content.html.twig -> it's also in the same directory.
In index.html.twig I have {% block body %}{% endblock %}.
My content.html.twig looks like:
{% extends 'GogsCMSBundle:Default:index.html.twig' %}
{% block body %}
Some content
{% endblock %}
I was looking solution on many forums, but nothing working. Symfony doesn't give me any errors - no effect.
When I try to use include in index.html.twig , it's work perfectly. Code below.
{% include "GogsCMSBundle:Default:content.html.twig" %}
I tried to use also another commands:
{% extends 'GogsCMSBundle:Default:index.html.twig' %}
{% extends 'GogsCMSBundle::index.html.twig' %}
{% extends 'GogsCMSBundle:index.html.twig' %}
{% extends '::index.html.twig' %}
{% extends 'index.html.twig' %}
All of them doesn't give any effect - no errors too.
My main controller:
return $this->render('GogsCMSBundle:Default:index.html.twig', array('name' => $page, 'menu' => $menu));
I cleaned Cache many times.
You need move indexd.html.twig in app\Resources\views = this is a base layout of the symfony. Next create in src/YourBundle/Resources/views layout.html.twig -which extend index.html.twig:
{% extends '::index.html.twig' %}
And finally, add in content.html.twig :
{% extends 'GogsCMSBundle::layout.html.twig' %}
More information there
#Artamiel found the answer...
Bug is in Controller. Contoller must indicate a content.html.twig.
So solution:
index.html.twig
{# src/Gogs/CMSBundle/Resources/views/Default/index.html.twig #}
{% block body %}{% endblock %}.
content.html.twig
{# src/Gogs/CMSBundle/Resources/views/Default/content.html.twig #}
{% extends 'GogsCMSBundle:Default:index.html.twig' %}
{% block body %}
Some content
{% endblock %}
Contoller.php
return $this->render('GogsCMSBundle:Default:content.html.twig');
I have splitted my layout and templates to few partials, mostly because of old Symfony1 habits.
file layout.html.twig:
...
<body>
{{ include("ABCBundle:Partials:breadcrumbs.html.twig") }}
{% block body %}{% endblock %}
</body>
...
file breadcrumbs.html.twig
<div class="abc">
{% block breadcrumbs %}
Home
{% endblock %}
</div>
file show.html.twig
{% extends "ABCBundle::layout.html.twig" %}
{% block breadcrumbs %}
{{ parent() }}
abc
{% endblock %}
{% block body %}
(something something)
{% endblock %}
Funny thing is, when I render show.html.twig, I can put data into body block, and everything works fine, but I can't do anything with breadcrumbs block. Whatever I do - write something inside that block or call parent(), nothing happens, only content from breadcrumbs.html.twig is being rendered. There's also no error about calling parent() and any other error related to extending block.
I think you should use {% include "..." %} rather than {{ include("...") }}
According to the twig documentation, the {% include %} tag "includes a template and returns the rendered content of that file into the current namespace" where as the include function "returns the rendered content of a template"
(Meaning the include function just returns the rendered content, where the tag adds the content to the current namespace which would include the blocks you defined)
Found the solution.
It looks like you can't extend block included in layout's include, from template extending this layout:
[partial.html.twig] --- [ layout.html.twig ] --- [ template.html.twig ]
{% block abc %} {% include 'partial.html.twig' %} {% extends layout.html.twig %}
{% block abc%} aaa {%endblock %}
You have to perform a little hack, including adding extra content to layout and replacing original block from partial.html.twig with conditional. More here: Overriding blocks within included Twig templates