How to get source of twig block in twig template? - symfony

I have following twig block in template which extends main layout:
{% block abc %}
{{ name }}
{% endblock %}
next I have a head block in the same template. I want to pass block abc as template for twig.js:
{% block head %}
<script type="text/html" id="template-abc">
{{ blocksource('abc') }}
</script>
{% endblock %}
so the rendering result is:
{{name}}
How can I do this?
I tried building "blocksource" function in twig extension, but I don't know how to access block source form here.
function blocksource( Twig_Environment $env, $blockname) {
$source = ???;
return $source;
}

Use verbatim tag, it will do what you want.
{% verbatim %}
{{ things_you_want_to_show_as_twig_template }}
{% endverbatim %}
Everything inside this tag will not be interpreted by twig engine.
You can read more on that in twig documentation.

Related

Display View in twig

I created (in Drupal 8) a view of a dataset (newsteaser_mit_bild) with some News in there.
With this view i created a block. The name is automatically generated (views_block__newsteaser_mit_bild_block_1).
The normal content is displayed with
{{ page.content }}
How can i display this View in my Twig File ?
{{ page.newsteaser_mit_bild }}
seems not to be right.
How can i use the view/block in my twig an how can i template them ?
In the main twig file you can use name block like this:
{% block my_custom_block }%
{% endblock my_custom_block %}
In the another twig file you can call the block like this:
{% extends 'link_for_file.twig' %}
{% block my_custom_block }%
{{ parent() }}
{% endblock my_custom_block }%
You can preprocess a new variable and use views_embed_view like:
function THEME-NAME_preprocess(&$variables, $hook) {
$variables['MY-VIEW-NAME'] = views_embed_view('VIEW-ID');
}
And then in the twig file:
{{ MY-VIEW-NAME }}

Include Twig template which Extends

I am rendering a Twig template as below:
$this->render('base.html.twig');
The content (simplified) of this Twig template looks as below:
{% block headers %}
...
{% endblock %}
{% block pagecontent %}
...
{# I want to include another template (A) here #}
{# I want to include another template (B) here #}
{% endblock %}
{% block footers %}
...
{% endblock %}
I have another Twig template which I am not rendering, but I want to include in the above template (where I have placed my Twig comment). The content is as follows:
{% extends '::base' %}
{% block headers %}
{{ parent() }}
{% endblock %}
{% block pagecontent %}
{{ parent() }}
...
{% endblock %}
I want to eventually render several Twig templates inside of base.html.twig.
Is what I am attempting to do achievable, and if so, how do I achieve it?
You just need to render child template (the one extending base.html.twig).
Change in your controller:
$this->render('child_template_extending_base.html.twig');
Replace child_template_extending_base with your real template name.
You can also embed another controllers views in your template with this code:
{{ render(controller(
'AppBundle:Article:recentArticles',
{ 'max': 3 }
)) }}
Read more about this feature here: http://symfony.com/doc/current/book/templating.html#embedding-controllers
base.html.twig
{% block headers %}
...
{% endblock %}
{% block pagecontent %}
...
{# I want to include another template (A) here #}
{# I want to include another template (B) here #}
{% endblock %}
{% block footers %}
...
{% endblock %}
Your controller:
$this->render('base.html.twig');
Normally, $this->render('view.html.twig'); accepts only one twig.
If you want to have several templates, you can build it like this:
view.html.twig
{% extends '::base' %}
{% block pagecontent %}
{# Controller function with template 1 #}
{{ render(controller('AppBundle:Article:recentArticles',{ 'max': 3 })) }}
{# Controller with template 2 #}
{{ render(controller('AppBundle:Article:relatedArticles',{ 'max': 4 })) }}
{% endblock %}
ANOTHER POSSIBLE SOLUTION IS :
You can break one block into several blocks.

Twig use function multiple parameter

I am looking for using function "{% use %}" with multiple parameter in twig template.
all page template
{% use "common.html.twig" with
container as containerParent,
title as titleParent
%}
{# Some code ... #}
common.html.twig
{% block title %}{{ block(titleParent) }} - Admin{% endblock %}
{% block container %}
{# Some code ... #}
{{ block(containerParent) }}
{# Some code ... #}
{% endblock %}
When I tried that, my block container and title are not modified.
Maybe I didn't understood the doc ? http://twig.sensiolabs.org/doc/tags/use.html
I just want have access to function twig {{ parent() }} in my twig file which is included by {% use ... %}
Any suggestion ?
Sorry for my English, I am learning it...

Toggle html validation globally

I've made a couple of twig extensions but I'm stumped on this one.
I have the following template logic that I want to make into an extension.
I need reuse this logic into many different forms instead of copying and pasting the following code everywhere:
{% if html5validation is not defined %}
{{ form_start(some_form) }}
{% else %}
{% if html5validation %}
{{ form_start(some_form) }}
{% else %}
{{ form_start
(
company, {'attr': {'novalidate': 'novalidate'}}
)
}}
{% endif %}
{% endif %}
With the above code from the controller I can do the following to turn the html5 validator on and off:
$this->render(..., array(html5validation => false));
I want put the template logic into the twig extension below...
I just don't know if it's possible to implement what I've done above in a twig extension.
class HTML5Validation extends \Twig_Extension
{
public function getFunctions()
{
return array(
new \Twig_SimpleFunction('html5validation', array($this, 'setValidation')),
);
}
public function setValidation($boolean)
{
//Implement the same logic as the twig template.
}
public function getName()
{
return 'html5validator';
}
}
The short answer is no - you can't do this using a twig extension, it's not what they're meant for.
Looking at your template fragment I'd say you need to customise the form_start block. To do this see Symfony Form Theming and How to customise form rendering.
EDIT: This solution does not work if your customised code requires local twig variables - only global twig variables are available for form theming. You can define your own twig globals in config.yml or in a twig extension.
For example, to override form_start globally, you find the default definition of the form_start block in form_div_layout.html.twig, copy it into your own form theme file e.g. YourBundle/Form/fields.html.twig, modify it as required and and update the twig configuration to apply your form theme file. Something like this:
{# src/YourBundle/Form/fields.html.twig #}
{% extends 'form_div_layout.html.twig' %}
{% block form_start -%}
{% if html5validation is not defined %}
{{ parent() }}
{% else %}
{% if html5validation %}
{{ parent() }}
{% else %}
{{ parent
(
company, {'attr': {'novalidate': 'novalidate'}}
)
}}
{% endif %}
{% endif %}
{%- endblock form_start %}
Config:
# app/config/config.yml
twig:
form:
resources:
- 'YourBundle:Form:fields.html.twig'
I actually found a better way to do what I wanted.
As a plus it works globally instead of having to populate more fields into your controller!
In YourBundle/Resources/views/validation.toggle.html.twig
{% extends 'form_div_layout.html.twig' %}
{% block form_start -%}
{% if html5validation is defined and html5validation == false %}
{% set attr = attr|merge({'novalidate': 'novalidate'}) %}
{% endif %}
{{ parent() }}
{%- endblock form_start %}
Then if you want to turn off html5 validation across the whole website:
# app/config/config.yml
twig:
global:
html5validation: false
Or
Even better just use it in your dev_config.yml if you want validation on by default on production mode but the ability to toggle validation on and off for dev mode.
# app/config/dev_config.yml
twig:
global:
html5validation: false
resources:
- 'YourBundle::validation.toggle.html.twig'
Finally use it in your twig template normally:
{% form_theme your_form 'YourBundle::validation.toggle.html.twig' %}
form_start(your_form)
Reusable and non invasive, exactly like I wanted it. :)
I got the hint from:
https://github.com/symfony/symfony/issues/11409#issuecomment-49358377
In the absence of a more elegant solution, you can always put the twig fragment given in your question into a separate file and use twig include from your various forms. The included fragment has access to the variables from the surrounding context:
{# YourBundle/Resources/views/form_start.html.twig #}
{% if html5validation is not defined %}
{{ form_start(some_form) }}
{% else %}
{% if html5validation %}
{{ form_start(some_form) }}
{% else %}
{{ form_start
(
company, {'attr': {'novalidate': 'novalidate'}}
)
}}
{% endif %}
{% endif %}
Then in the twig file for the form:
{% include 'YourBundle::form_start.html.twig' %}
If you typically pass a 'form' variable into render() in your controller(s) then you can use that in your form_start fragment. Otherwise you can pass the appropriate form in as a variable:
{% include 'YourBundle::form_start.html.twig' with {'form': localForm} %}

Twig Custom Extension - call parent() in extending block

is there any way to call parent() function in extending block in the template of the custom extension?
In my base.html.twig I have block footer_javascript and in my custom extension I would like to add some JS to this block but I need to ensure that original block footer_javascript will be extended not overwritten. I tried this:
custom_extension.html.twig:
{# some html/twig code, not really important #}
{% block footer_javascript %}
{{ parent() }}
{# some javascript for this custom twig extension #}
{% endblock footer_javascript %}
but of course, I get
Calling "parent" on a template that does not extend nor "use" another
template is forbidden
base.html.twig - base template with block structure:
{# base html/twig structure, not really important %}
{# block which will be extended/overwriten in templates which extends this base.html.twig #}
{% block footer_javascript %}
{% endblock footer_javascript %}
extended.html.twig - template which extends base.html.twig; in this template I am using custom twig extension:
{% extends "::base.html.twig" %}
{# some html/twig ... #}
{{ custom_extension(entity) }}
{% block footer_javascript %}
{{ parent() }}
{# javascript used for extend.html.twig #}
{% endblock footer_javascript %}
Is there any way to extend base footer_javascript in my custom extension template?
To use parent(), you have to extend the template.
Your custom_extension.html.twig has to extend base.html.twig like extended.html.twig.
EDIT:
If you're using 2 templates with <body>, you don't have to use {{ parent() }}, but instead put your js in a twig that you will include in your block.

Resources