I'm wondering how I would go about using custom variables in base.html.twig in a symphony application.
I know I can use {{ app.whatever }} but how would I use {{ myvariable }} or {{ myentity.row }} if I wanted to?
Thanks
As a variable is rendered with a twig template, you can use this variable in both parent and child templates.
In other words, if you have the following base template:
// base.html.twig
<html>
<body>
{{ block body }}
{{ endblock }}
</body>
</html>
The following child template:
// child.html.twig
{% extends 'base.html.twig' %}
{% block body %}
// content
{% endblock %}
And the following controller action:
public function renderVariableAction()
{
return $this->render('child.html.twig', [
'hello' => 'Hello world',
]);
}
You can use {{ hello }} in both base.html.twig and child.html.twig.
EDIT
For a global variable:
// app/config/config.yml
# ...
twig:
# ...
globals:
your_custom_var: "your_value"
You can't define a variable that is always assigned to a specific template, the variable must be rendered with it dynamically.
Note You can define global variables dynamically like this:
$this->get('twig')->addGlobal('entity', $entity);
So you can easily inject the same variable on kernel.response using an EventListener.
See global variables in templates.
Related
I have defined a variable in a page:
{% set service = builderDetails.record %}
and I want to pass this variable to a component:
{% component 'Variations' service=service %}
but this method does not work. How can I do that?
I am guessing that you need to pass builderDetails.record to your component 'Variations'
and then you want to access that variables inside component 'Variations''s default.htm and show some details about it.
for that you need to utilize component's onRender method
inside your component 'Variations'
public function onRender()
{
$this->page['record'] = $this->page->components['builderDetails']->record;
}
$this->page->components is holding all the components available in page as array.
builderDetails is alias of the component Record Details(Builder Plugin) which is added in to page.
now inside your default.htm
you can access record variable and use it as you desire
{{ record.name }}
we assume here that your record has attribute name
if you need anything please comment.
In a Twig .htm partial
<div class="sidebar-widget">
{% component "postBlock" score=55 name="Johan" %}
<div class="nonsense meta">
{% partial 'nonsense' score=75 name="Marga" %}
</div>
</div>
In the nonsense twig that is a child of the previous .htm partial
<div class="sidebar-element">
<div>My name is: {{ name|default('John Doe') }}</div>
<div>My score is: {{ score|default('No score') }}</div>
</div>
In the component postBlock, onRender function
function onRender() {
$score = $this->property('score'); // 55
$name = $this->property('name'); // Johan
}
To pass from a parent twig to a child twig, you don't have to use the onRender function
in the component, only if you want to modify things and pass is from there to the twig.
You dont have to assign it to page. You can access it via:
__SELF__.property('property_name')
After definin property in component:
{% component 'Variations' service=service %}
In your components default.htm
{{__SELF__.property('service')}}
I have a function in my Symfony controller which returns the following:
test+testString1+test2
TestController.php
public function getResultAction($fileName) {
$string1="test";
$string2="testString1";
$string3="test2";
$response = $string1."+".$string2."+".$string3;
return new Response($response);
}
In my twig I've rendered the function in my controller:
test.html.twig
{% set test %}
{{ render(controller('TestBundle:Test:getResult')) }}|split('+', 4)
{% endset %}
{{ test[0] }}
I'm using twig split filter so that I can display test, testString1 and test2 individually. But then whenever I attempt to display test[0], I receive the following error:
Impossible to access a key "0" on an object of class "Twig_Markup" that does not implement ArrayAccess interface in TestBundle:Test:test.html.twig
What's wrong with what I'm doing? I hope you could help me with this. Thanks
You miss the split filter inside the double brace as follow:
{% set test %}
{{ render(controller('TestBundle:Test:getResult')) |split('+', 4) }}
{% endset %}
Hovenever seems same problem with the set tag. From the doc:
The set tag can also be used to 'capture' chunks of text
Try with:
{%
set test=render(controller('TestBundle:Test:getResult'))|split('+', 4)
%}
Hope this help
I am trying to make a messaging system and I'm facing a small problem. I have a bigger template that displays my menu and my content. The menu includes the number of new messages, and the content can be any page(compose a new message, inbox, sent).
The problem is that I have to render each of the small templates by passing the number of new received messages to each of them, calling the doctrine each time and repeating code. Is there any way to send the number only to the parent template?
Here are my templates:
This is the parent containing the newmsg variable that gives me problems.
{% extends "::base.html.twig" %}
{% block body %}
inbox : {{ newmsg }}
sent
compose
{% endblock body %}
Here is an example of child template:
{% block body %}
{{ parent() }}
{% if messageList %}
{% for message in messageList %}
<li>title = {{ message.title|e }}</li>
<li>cont= {{ message.content|e }}</li>
<li>data= {{ message.date|date('d-m-Y H:m:s') }}</li>
<li>sender= {{ message.sender|e }}</li>
<hr>
{% endfor %}
{% else %}
<div>no messages</div>
{% endif %}
{% endblock body %}
The problem is that each child template is asking me for the newmsg variable
$messages = $this->getDoctrine()->getRepository('MedAppCrudBundle:Message');
$newMessagesNo = count($messages->findBy(array('seen' => '0', 'receiver' => $this->getUser())));
return $this->render(
'MedAppCrudBundle:UserBackend\Message:new.html.twig',
array(
'form' => $form->createView(),
'newmsg' => $newMessagesNo,
)
);
And I have to write this in every single controller. Any way I can shorten this problem?
You could implement a service that gives back the newmsg value and call it on your parent template. Then it would not be necessary to pass the variable.
You can add a service in your bundle's services.yml with something like:
services:
newmessages:
class: Full\Class\Name\NewMessagesService
arguments: ["#doctrine.orm.entity_manager"]
Then, implement the Full\Class\Name\NewMessagesService class. Keep in mind that this class will need a constructor that receives an EntityManager argument. Something like:
<?php
namespace Full\Class\Name;
class NewMessagesService{
private $entityManager;
public function __construct($entityManager){
$this->entityManager = $entityManager;
}
public function methodToCalculate(){
//Perform calculation and return result
}
}
Then, in your parent template, replace {{newmsg} with:
{{ newmessages.methodToCalculate() }}
Hi how use this part of code with twig,
$this->assign('title', 'Home');
not
echo $this->assign('title', 'Home');
I tried,
{% set assign = ('title', 'Home') %}
{% set this.assign = ('title', 'Home') %}
{% set assign = {'title', 'Home'} %}
{{ assign('title', 'Home') }}
But still don't work
Thanks you
I don't know about using $this in the context of a template (it would refer to some generated class instance), but you can perform arbitrary operations without printing by using the do statement.
The do tag works exactly like the regular variable expression ({{ ... }}) just that it doesn't print anything:
{% do 1 + 2 %}
To access the view itself when using TwigView, use the _view variable:
{% do _view.assign('title', 'Home') %}
i can't figure out, how to render a macro in Symfony 2 controller. This is how i can render a twig template
$this
->get("twig")
->render("AcmeBundle:Product:table.html.twig", array(
"product" => $product
))
;
So i searching for something similar, but for rendering a twig macro. Thx for any suggestions!
Twig macro's are something inside a template. They are run whenever you render a template executing the macro.
Just create another "wraper" template, which would have only that macro in it. Something like
macro.html.twig file
{% macro sample(item) %}
{# some code here #}
{% endmacro sample #}
sample_macro_wrapper.html.twig
{% from 'macro.html.twig' import sample %}
{{ sample(item) }}
controller.php
public function someAction()
{
// ...........
$renderedMacro = $this->get('twig')
->render('sample_macro_wrapper.html.twig', ['item' => $item]);
}