I'm working on the frontend of a project using Symfony2. I'm stock with something that must be simple, but it's costing me a lot of time.
layout.html.twig is located at /FrontBundle/Resources/views with the following lines
{% include 'SitewebFrontBundle::sidemenu.html.twig' %}
{% block sidemenu %}{% endblock %}
sidemenu.html.twig is also located at /FrontBundle/Resources/views.
Side menu has different content depending on the page been viewed. The urls are:
address.com/menu1/...
address.com/menu2/...
address.com/menu3/...
What I want to do is to create a statement on sidemenu.html.twig following a logic like:
if {{ app.request.requesturi }} has /menu1/
show menu1
else if {{ app.request.requesturi }} has /menu2/
show menu2
else
show menu3
Any ideas on how to accomplish this?
Also you can use KnpMenuBundle. then create merge all your menus under a single root.e.g: make a menu like
Menu
menu1
foo
menu2
...
then make a twig extension, inject the request into it, and find which branch (menu) you have to display:
//in your extension class:
findBranch(){
$path = $this->request->getPathInfo();
$path = trim($path, '/');
$parts = explode('/', $path);
$branch = $parts[0];
return $branch;
}
then in your template find the active branch using the extension and render it with using the built-in method
Generate your sidemenut.html.twig by a passed parameter:
# sidemenu.html.twig
{% if requestUri is not defined %}
{% set requestUri = 'menu3' %}
{% endif %}
# render your routes here like so:
Route 1
# ...
And now include the sidemenu.html.twig with parameters:
# this will result in the requestUri variable to be menu1:
{% include 'SitewebFrontBundle::sidemenu.html.twig' with {includeUri: 'menu1'} %}
# use the request uri as a parameter:
{% include 'SitewebFrontBundle::sidemenu.html.twig' with {includeUri: app.request.requesturi} %}
# this will fallback to 'menu3':
{% include 'SitewebFrontBundle::sidemenu.html.twig' %}
For more questions check out:
The docs about including templates
An evaluation about include vs. render
Why can't you just put all menus into one twig and include them with a variable to determine what menu should be used? Or you can send required name to template from your controller. Because putting such logic into twig usually is a bad idea
Related
I'm building a multisite eZ Platforme installation and I need to specify a main layout for my templates.
Right now I have a template article.html.twig :
{% extends "main_layout.html.twig" %}
{% block content %}
<h1>{{ ez_render_field(content, 'body') }}</h1>
{% endblock %}
what I want to do is something like this :
{% if(siteaccess = "site1"){
extends "site1_main_layout.html.twig"
}
else if(siteaccess = "site2"){
extends "site1_main_layout.html.twig"
}
%}
Please help me!
You can just configure the layout in the config:
ezpublish:
system:
site1:
pagelayout: "tpl1.html.twig"
site2:
pagelayout: "tpl2.html.twig"
After that, you can just use the following in your full view:
{% extends pagelayout %}
{% block content %}
...
{% endblock %}
pagelayout is a variable prepopulated by eZ Platform from the above config based on current siteaccess. It requires eZ Platform 1.2 at the least, I believe.
It should also be noted that pagelayout variable is available only in full view templates. Other templates wishing to use the configured pagelayout must use the following:
{% extends ezpublish.configResolver.parameter('pagelayout') %}
Correct me if I misunderstood your goal, but do you recon it could be sorted by checking the domains? (I am assuming they would be different so could serve as a separator):
{% if app.request.baseUrl == 'site1' %}
...
{% else %}
...
{% endif %}
If I am not wrong, I also belive you can create a default Twig Controller Loader to decide this beforehand instead of leaving the logic to your views :)
Have a look here https://doc.ezplatform.com/en/latest/guide/design_engine/
you can use the Design engine where you can set up different themes with fallback.
Define one base theme an add per siteaccess one extra theme where you can override any template.
In Twig with Symfony, to generate a path in a template, it wants to use
{{ path('mypathname', {parameterName: parameterValue}) }}
In my project I have an inherited template, and one block loops through a chunk of data and spits out a list of URL's. What I want to do, is from my new template, is allow me to {% set %} the keyname of the first parameter
so basically like this
template.html.twig
<ul>
{% for thing in things %}
<li>{{ thing.name }}</li>
{% endfor %}
</ul>
otherthings.html.twig
{% extends 'template.html.twig' %}
{% set path_name = "thingDetail" %}
{% set path_param = "id" %}
and see the output like
<ul>
<li>The 20th Thing</li>
</ul>
It may sound ridiculous, but across this app, the naming and pathing styles doesn't always match up with the different kinds of content that goes into that blocks loop, so some type of override needs to happen and the last thing I want to do right now, is overwrite the block for that for each type, when the last thing that needs to be done is URL generation
Thank you!
If you enclose the hash key in parenthesis, Twig will treat it as an expression:
{%- set field = 'foo' -%}
{%- set arr = { (field): 'bar' } -%}
will set arr to
{ foo: 'bar' }
(This is mentioned in the Twig documentation, but it's easy to see how it could be overlooked.)
I need to load a page, that will be "inserted" in a template - as I read it, Volt's Template Inheritance should do the trick and it does... kinda. Hardcoded values, as shown in the examples, work fine - the following example works:
<!-- Template -->
<div id="site_content">
{% block test %}
{% endblock %}
</div>
and the page, that inherits the template:
{% extends "../../templates/de/index.volt" %}
{% block test %}
{{ content() }} {# this is a registered volt function that outputs the generated content #}
{% endblock %}
However, the same page might need to inherit a different template and that must be decided on runtime, so the name of the template must be generated dynamically. Two options occurred to me:
Set the template name to a variable and use it when extending - the problem here is that I don't see a way to use it afterwards. That guy seems to have had the same problem, but there is neither an answer of how to do it, nor a confirmation that it isn't possible at all.
Register another function to generate the complete string (e.g. {% extends "../../templates/de/index.volt" %}) and then compile it, e.g.
$compiler->addFunction('get_template',
function ($resolvedArgs, $exprArgs) use ($volt) {
return $volt->getCompiler()
->compileString('{% extends "../../templates/de/index.volt" %}');
});
and then use that function in the page, e.g.
{{ get_template() }}
{% block test %}
{{ content() }}
{% endblock %}
However, using that approach does not parse the page content (e.g. the content returned by the registered content() function is not shown). I'm also open to other solutions (using Twig instead of Volt is only a last resort, for performance issues), advices of what I'm doing wrong or pointers of useful articles on the topic. Thanks in advance!
Try using partials as documented in the Phalcon doc: Using Partials
On my eZ publish 5 site I have all my templates in Twig, in the vendor/ezsystems/demobundle/EzSystems/DemoBundle/Resources/views/ subfolders. They are all being used throughout my whole site, no problems there. With one exception: 404 pages. If I go to mysite/nonexistingurl, it gives me a kernel (20) / Error page, with status 404. The template being used for this is the 20.tpl somewhere in eZ publish/symfony, I don't want that, I want to use my own Twig template for this.
How can I achieve this? I added a vendor/ezsystems/demobundle/EzSystems/DemoBundle/Resources/views/Exception/error.html.twig page, but this one is not being called
first add this configuration parameter
parameters:
ezpublish_legacy.default.module_default_layout: 'YourBundle::pagelayout_legacy.html.twig'
you may add it in the parameters.yml file located in path/to/yourezpublishinstall/ezpublish/config, the parameters.yml is usually imported in the config.yml located in the same folder
this would define the twig template located in path/to/yourbundle/Resources/views/pagelayout_legacy.html.twig as the parent template for legacy stack modules templates
inside the pagelayout_legacy.html.twig template, you may use this code
{% extends 'YourBundle::pagelayout.html.twig' %}
{% block content %}
{# module_result variable is received from the legacy controller. #}
{% if module_result.errorCode is defined %}
<h1>{{ module_result.errorMessage }} ({{ module_result.errorCode }})</h1>
{% else %}
{{ module_result.content|raw }}
{% endif %}
{% endblock %}
note in the code, the template extends the pagelayout.html.twig template, that should here define a block named content, the pagelayout.html.twig may usually be the main base layout for your ez publish 5 website
you may modify the pagelayout_legacy.html.twig template to your needs
reference:
http://share.ez.no/forums/developer/overriding-legacy-error-pages-templates
Instead of doing this rendering of each slide in my TWIG like this (see line 6):
{# loop out the slides #}
{% for c in contents %}
{% set i=i+1 %} {# increase slide number #}
<div id="slide{{ i }}" class="slide" style="z-index:{{ i }};">
{# the slide itself, rendered by it's own template #}
{% include 'BizTVArchiveBundle:ContentTemplate:'~c.template~'/view.html.twig' with {'contents': c, 'ordernumber': i} %}
</div>
{% endfor %}
...Instead I would like to keep all of that logic in the controller, to just deliver to the view an array of ready slides. How can I do something like this (see line 9):
//do stuff...
foreach ($container->getContent() as $c) {
$content[$i]['title'] = $c->getTitle();
$content[$i]['sort'] = $c->getSortOrder();
$content[$i]['data'] = $c->getData();
$content[$i]['template'] = $c->getTemplate()->getId();
$content[$i]['duration'] = $this->extract_seconds($c);
$content[$i]['html'] = $this->render('BizTVArchiveBundle:ContentTemplate:'.$content[$i]['template'].'/view.html.twig', array(
'contents'=> $content[$i],
'ordernumber' => 99,
));
}
All it gives me at the moment (the contents of $content[$i]['html']) is
{"headers":{}}
Within a twig template, you can set the value of a printed variable like this:
{% set rendered %}
{{ var_to_print }}
{% endset %}
You can get content form rendered object like this:
$this->render('BizTVArchiveBundle:ContentTemplate:Some.html.twig', array())->getContent();
It's better if you include the template in the template, this way you keep the templating rendering in the view layer and the logic in the controller layer.
But well, if you really want it...
You can use 2 services to do that: twig is using the Twig_Environment or templating.engine.twig which is a templating layer build in Symfony2 for Twig, this can be easily switched ot templating.engine.php.
If you use the twig service, you can see the twig docs on how to use it:
$template = $this->get('twig')->render('/full/path/to/Resources/views/'.$content[$i]['template'].'/view.html.twig', array(...));
If you use the templating.engine.twig service, see the templating docs on how to use it, which is almost exact the same as the Twig_Environment.
That is because $this->render() returns a Response object.
Instead of $this->render(), use $this->renderView().