I'm working on a Symfony2 application and I'm trying to import resources (here, css and js) in a specifig twig template, instead of in the layout templates. However, what I've tried doesn't seem to work when I use the extends property. Yet it does work when there is no layout inheritance.
Here's the code I used :
{% block stylesheets %}
{% stylesheets 'bundles/mybundlename/css/style.css'
filter='cssrewrite' %}
<link rel="stylesheet" href="{{ asset_url }}" type="text/css" />
{% endstylesheets %}
{% endblock %}
{% block javascripts %}
{% javascripts 'bundles/mybundlename/js/jquery-1.7.2.min.js'
'bundles/mybundlename/js/jquery-ui-1.8.20.custom.min.js'
%}
<script src='{{ asset_url }}' type='text/javascript'></script>
{% endjavascripts %}
{% endblock %}
{% extends "MyBundle::layout.html.twig" %}
... the rest of my template ...
Bottom line, how would I import those resources in my inheriting template?
Or is it simply better to just import them in the general layout (but then it loads for every page :/) ?
Edit : I have used #MyBundle route types as well, and they are being searched by the engine (if the path is wrong, I get an error), but the resources are not added the the html section.
Second edit : The reason why it was not working is likely that I hadn't declared the {{% blocks %}} in my top level layout. I did and used {{ parent() }} (as a matter of "cleanliness") in my sub layouts and pages, and it works.
{% extends ... %} must come first.
You might also want to use the parent function to append to the stylesheets and javascripts defined in the layout instead of overwriting them.
Related
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
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 %}
I need some variables(constant) in my project:
path_to_root
path_to_images
I would like to make it without php, just Twig, so i create main.twig:
main.twig:
{% set path_to_root = "/some_folder" %}
{% set path_to_images = "/some_images" %}
In second template i extends by main.twig, so
template.twig
{% extends "main.twig" %}
{% block some_block %}
some_text
<img src="{{ path_to_images }}/image.png" />
{% endblock %}
Yes, it works, bu my question:
Is this good way for having main.twig and in child extends with main?
In each file of templates will i must extends with main.twig?
Sorry for my english :(
Not sure about other php files but the images should go in the assets folder which then you can import using
<img src="{{ asset('path/to/folder/image.png') }}" />
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
i want to override a css file i.e reside in sonata-project/admin-bundle/Sonata/AdminBundle/Resources/public/bootstrap/css path of sonata admin bundle project.
Please help me out.
One way you can you override the css files of sonata admin but remember this will override the block of stylesheets but still you can call the stylesheets of parent block by calling {{ parent() }}
{% block stylesheets %}
/* this will override the parent block you can define here your css files*/
<link rel="stylesheet" href="{{ asset('cssfilepath.css') }}"/>
{% endblock %}
{% block stylesheets %}
/*this will extend the parent block */
{{ parent() }}
<link rel="stylesheet" href="{{ asset('cssfilepath.css') }}"/>
{% endblock %}
I used the answer of M Khalid Junaid that is working like a charm. Here some facts I missed while implementing this.
Update your config.yml like this:
sonata_admin:
templates:
list: AppBundle::Admin/list.html.twig
The src/AppBundle/Resources/views/Admin/list.html.twig then can look like this:
{% extends 'SonataAdminBundle:CRUD:base_list.html.twig' %}
{% block stylesheets %}
{{ parent() }}
<style type="text/css">
* {
}
</style>
<!-- and/or -->
<link rel="stylesheet" href="{{ asset('cssfilepath.css') }}"/>
{% endblock %}
It is possible to remove/add stylesheets in Sonata Admin Bundle within configuration file without handling template files:
sonata_admin:
assets:
remove_stylesheets:
- bundles/sonataadmin/css/old.css # path to vendors css-file to remove
extra_stylesheets:
- build/admin/css/new.css # your css-file to add
Considered above options are listed in Sonata Admin Bundle CONFIGURATION in FULL CONFIGURATION OPTIONS section.