Using variables from inside symfony 2 / twig blocks - symfony

I have this
base.html.twig
<html>
{% block template_scope_vars %}
{% endblock %}
<head></head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
user.html.twig
extends base...
{%block template_scope_vars %}
{% set test= "bippo" %}
{%endblock%}
{%block content %}
{{ test }}
{% endblock %}
Error
Variable "test" does not exist
Ok please please don't tell me that I don't have to use blocks for this, the use case is more difficult than this simple example obviously. The idea is that test gets available in the base.html.twig as well, as well as any sub-templates of it that I might be using in future

for the special use case I had I could use this. It is a shame though, there is no neater solution. All other solution I could come up with, would require to create a new file for each set of template scope variables. Which plain sucks
base.html.twig
<div id="menu"> //this is like a sidebar menu
<div class="menuitem {% block foo %}{% endblock %}">
Foo
</div>
<div class="menuitem {% block bar %}{% endblock %}">
Bar
</div>
<div>
{% block content %}
{% endblock %}
Then in
foo.html.twig
{% extends "MyBundle::base.html.twig" %}
{% block foo %}active{% endblock %}
{% block content %}
Some content specific for foo
{% endblock %}
bar.html.twig
{% extends "MyBundle::base.html.twig" %}
{% block bar%}active{% endblock %}
{% block content %}
Some content specific for bar
{% endblock %}
and then you set the css for the background of e.g.
CSS
menuitem.active {
background-color: red;
}

base.html.twig
<div id="menu"> //this is like a sidebar menu
<div class="menuitem{{ active == 'foo' ? ' active' : '' }}">
Foo
</div>
<div class="menuitem{{ active == 'bar' ? ' active' : '' }}">
Bar
</div>
<div>
{% block content %}
{% endblock %}
foo.html.twig
{% extends "MyBundle:Whatever:base.html.twig" %}
{% block content %}
{{ content }}
{% endblock %}
Controller
/**
* #Route("/foo", defaults={"param" = null}, name="foo")
* #Route("/foo/{param}", name="foo_with_param")
* #Template()
*/
public function fooAction($param)
{
// This would really be getting data from the Model
if ($param == 'something') {
$content = 'Some content';
$active = 'foo';
} else {
$content = 'Different content';
$active = 'bar';
}
return array(
'content'=> $content,
'active' => $active,
);
}
When rendering foo.html.twig, base.html.twig will get the variable "active".

Related

Variable "organization_name" does not exist. when call new oro action

I created new controller and new view
<?php
namespace My\ProductBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class ProductController extends Controller
{
/**
* #Route("/GetProducts")
*/
public function GetProductsAction()
{
return $this->render('MyProductBundle:Product:get_products.html.twig', array(
));
}
}
view:
{% extends "::base.html.twig" %}
{% block title %}MyProductBundle:Product:GetProducts{% endblock %}
{% block body %}
<h1>Welcome to the Product:GetProducts page</h1>
{% endblock %}
when try to access this action /GetProducts
I got the following error:
Variable "organization_name" does not exist.
Stack Trace
in vendor\oro\customer-portal\src\Oro\Bundle\FrontendBundle\Resources\views\Organization\logo_frontend.html.twig at line 3 -
{% set route = 'oro_frontend_root' %}
{% if isDesktopVersion() %}
{% if organization_name|length %}
{% set logo = oro_theme_logo() %}
<h1 class="logo logo-{{ logo ? 'image' : 'text' }}">
<a href="{{ path(route) }}" title="{{ organization_name }}">
Ayman Hussein.
You should extend more specific template than ::base.html.twig.
For example, your view can looks like
{% extends 'OroFrontendBundle:actions:view.html.twig' %}
{% block title %}MyProductBundle:Product:GetProducts{% endblock %}
{% block body %}
<h1>Welcome to the Product:GetProducts page</h1>
{% endblock %}
before {% if organization_name|length %} add another condition to check if the var is already defined or not: {% if organization_name is defined %}

Template does not always see its variables

I will first present to you the incriminated templates.
To begin with, I have my layout template with the JQuery. To avoid multiple "$(document).ready()" I placed a block after the general JavaScript.
{# layout.html.twig #}
<script type="text/javascript">
$(document).ready(function(){
//Some JS
{% block jquery %}
{% endblock %}
});
</script>
{# Some HTML & JS #}
<body>
<!-- Some HTML -->
<div>
{% block content %}
{% endblock %}
</div>
<!-- Some more HTML -->
</body>
It is extended by the template layout_cart.html.twig.
{# layout_cart.html.twig #}
{% extends 'AppBundle::layout.html.twig' %}
{% block content %}
<h1>{% block titre %}{% endblock %}</h1>
<div id="content-container">
{% block subcontent %}
{% endblock %}
</div>
{% endblock %}
Which is extended itself by panier.html.twig
{# panier.html.twig #}
{% extends AppBundle:layout_cart.html.twig #}
{# Some code #}
{% block jquery %}
// Some JavaScript
{% for produit in produits %}
// Generating some JavaScript
{% endfor %}
{{ dump(produits) }}
{% endblock %}
{% block subcontent %}
{% if produits is defined and produits|length > 0 %}
{{ dump(produits) }}
{# Interacting with the variables #}
{% endif %}
{% endblock %}
The dump in the jquery renders this :
<pre class='xdebug-var-dump' dir='ltr'>
<b>array</b> <i>(size=0)</i>
<i><font color='#888a85'>empty</font></i>
</pre>
While in the subcontent it renders my objects collection.
Am I missing something ?

Twig blank page ( using 3 templates model and inheritance mechanism)

I'm following a tutorial about symfony2 framework ..
I've already managed to render a template which inherits from the base layout as follows
# ::layout.html.twig > MyvendorBlogBundle:blog:index.html.twig
# then inside the controller action, call
$this->render('MyvendorBlogBundle:Blog:index.html.twig', ['foo'=>'bar']);
I decided to add an intermediate template in between but I'm having trouble to make twig templating engine to render my 3 layouts cascaded templates: As mentioned above, i'm not able to get any output using the following schem but a blank page instead (no raised exceptions and the source only contains the base.html.twig code)
# ::layout.html.twig > MyvendorBlogBundle::layout.html.twig > MyvendorBlogBundle:blog:index.html.twig
Here are my templates
base (app/Ressources/views):
<html>
<head>
<meta charset="UTF-8" />
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}{% endblock %}
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
</head>
<body>
<div id="app-container">
<header id="app-header">
</header>
<div id="app-page-content">
{% block body %}{% endblock %}
</div>
</div>
{% block javascripts %}{% endblock %}
{# FLASH BAG HANDLING #}
{% for label, flashes in app.session.flashbag.all %}
{% for flash in flashes %}
<div class="alert alert-{{ label }}">
{{ flash }}
</div>
{% endfor %}
{% endfor %}
</body>
</html>
Then the blog bundle layout (src/Myvendor/BlogBundle/Resources/views):
{% extends "::base.html.twig" %}
{% block body %}
{% block side %}
<div id="blog-side">
<nav>
1rst link
</nav>
</div>
{% endblock %}
{% block main %}{% endblock %}
{% endblock %}
Now the index page template (src/Myvendor/BlogBundle/Resources/views/Blog):
{% extends "MyvendorBlogBundle::layout.html.twig" %}
{% block main %}
<h1>{{ caption }} !</h1>
{% if caption is not empty %}
{{ caption }}
{% endif %}
{% endblock %}
And finally the controller
namespace Myvendor\BlogBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
class BlogController extends Controller
{
public function indexAction()
{
return $this->render('MyvendorBlogBundle:Blog:index.html.twig', ['caption'=>'hello!']);
}
}
May someone spot what's going on here ?
The pb maybe obvious but I've been stuck for a couple of hours now and blocks nesting seems perfect to me :/

Using TWIG variables from children template

Need to use a variable that is in the parent template.
I have layout:
<html>
<head>
</head>
<body>
{%block content %}
{% set com = 0 %}
DEFALUT CONTENT
{% endblock %}
</body>
</html>
And children template:
{% extends '::layout.html.twig' %}
{% block content %}
HOW USE LAYOUT VARIABLE HERE? LIKE: {{ com }}
{% endblock %}
Thanks in advance!
Use the parent() twig function.
{% extends '::layout.html.twig' %}
{% block content %}
{{ parent() }}
{{ com }}
{% endblock %}
The above code will render a template like :
<html>
<head>
</head>
<body>
{% block content %}
{% set com = 0 %}
DEFAULT CONTENT
{{ com }}
{% endblock %}
</body>
</html>

Is a Twig block empty? - Symfony 2

I have a twig template with the following block:
{% block dashboard %}
{% include "::user_dashboard.html.twig" %}
{% endblock dashboard %}
Later in that template, I want to set a class on a div based on whether or not there is anything in that block (i.e., by default, it will have the include above, but children of this template may override it and empty it out).
What I had (that somewhat worked) was ...
{% set _dashboard = block('dashboard') %}
{% set _mainWidth = ( _dashboard|trim is empty ? "no-dashboard" : "with-dashboard" ) #}
<div id="main" class="{{ _mainWidth }}">
The problem here is that whole dashboard block gets called twice. This wouldn't bother me too much except that block renders a few controller actions, i.e. ...
{% render "UserWidget:userAppMenu" %}
... and the code in that action is being called twice. For various reasons, not the least of which is performance, this messes with some of the stuff in that dashboard block.
So, my question is ... is there any way to tell if that block is empty without loading it twice? Is there something really simple I'm missing or is this even possible?
Thanks!
EDIT:
Here is my full template if it helps clarify things:
{% extends '::base.html.twig' %}
{% block layout %}
{% block header %}
{% include "::header.html.twig" %}
{% endblock header %}
<div id="container" class="row-fluid">
{% block dashboard %}
{% include "::user_dashboard.html.twig" %}
{% endblock dashboard %}
{% set _dashboard = block('dashboard') %}
{% set _mainWidth = ( _dashboard|trim is empty ? "no-dashboard" : "with-dashboard" ) %}
<div id="main" class="{{ _mainWidth }}">
<h1 class="page-title">{% block page_title %}{% endblock %}</h1>
{% block main_filters %}{% endblock %}
{% if app.session.flashbag.has('message') %}
<div class="alert alert-block alert-success">
<ul>
{% for flashMessage in app.session.flashbag.get('message') %}
<li>{{ flashMessage }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% if app.session.flashbag.has('warning') %}
<div class="alert alert-block alert-success">
<ul>
{% for flashWarning in app.session.flashbag.get('warning') %}
<li>{{ flashWarning }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% block body %}{% endblock %}
{% block footer %}
{% include "::footer.html.twig" %}
{% endblock footer %}
</div>
</div>
{% endblock layout %}
Here you can see on lines 11 and 15 - both of those actually seem to include and process what is in that include.
What about this? This way the block should only be rendered once, when you call block('dashboard').
{# at top of twig #}
{% set _dashboard = block('dashboard') %}
{# where ever you include your block #}
<div>
{{ _dashboard|raw }}
</div>
{# and your main #}
{% set _mainWidth = ( _dashboard|trim is empty ? "no-dashboard" : "with-dashboard" ) #}
<div id="main" class="{{ _mainWidth }}">

Resources