Is it possible (and how) to automatically include specific macro files into every twig file by using PHP (not Twig lang).
Example: I got the file select2 which contains macros to define
select2 selections. Now the Twig environment autoincludes every macro
in that file under select2.macroname and without calling import in
other twig files I can use that macro?
I'm using twig standalone.
U could inject the file containing the macro's as a global variable into twig
$twig->addGlobal('my_macros', $twig->loadTemplate('macros.html'));
macros.html
{% macro HelloWorld(foo) %}
{{ foo }}
{% endmacro %}
random_file.html
{{ my_macros.HelloWorld('StackOverflow') }} {# output: StackOverflow #}
UPDATE April 2022
If you are looking for a method to auto-load macros in twig 3.X then have a look at the following answer
Related
I am looking to make macros available inside of the articles for my flask blog. When the body of my blog changes I run the following code to render the body into HTML:
target.body_html = bleach.linkify(bleach.clean(render_template_string(value),tags=allowed_tags, attributes=allowed_attr, strip=True))
render_template_string(value) is the part I'm concerned about. To use a macro inside of the template string (value), every single string has to include the following in order for me to use the macros from this file in the article body:
{% import "includes/macros.html.j2" as macros %}
This would not be reasonable to ensure that writers have access to the macros that I write in all of their articles. Is there any way to pass that argument via the render_template_string() function so that it doesn't have to be defined in every string? Or to otherwise create a template that the string is rendered inside of? Something like the following:
render_template_string(string,macros=function_to_import_macros("includes/macros.html.j2"))
While there does not appear to be a solution to pass an entire macros template as context, get_template_attribute does appear to allow you to pass individual macros one at a time. Example:
includes/macros.html.j2:
{% macro hello() %}Hello!{% endmacro %}
{% macro hello_with_name(name) %}Hello, {{ name }}!{% endmacro %}
Template rendering code:
hello = get_template_attribute("includes/macros.html.j2","hello")
hello_with_name = get_template_attribute("includes/macros.html.j2","hello_with_name")
return render_template("index.html", hello=hello,hello_with_name=hello_with_name)
index.html:
{{ hello() }}
{{ hello_with_name("Bob") }}
This solution will allow for adding individual macros to the context while rendering a template or template_string and can even be added to the global context via this method. If anyone knows how to add an entire template full of macros, that'd rock, but this allows the basic needed functionality.
I am refactoring some old twig templates, where many variables are passed to the templates but not declared in doc comments (which also work in PhpStorm for type hinting), like this:
{# #var user AppBundle\Entity\User #}
{# #var message string #}
<p>Hello {{ user.fullName }}!</p>
<p>{{ message }}</p>
Is there a tool that can pre-generate these doc comments from variables used in a template, ideally usable as PhpStorm plugin?
It will be good enough if it would extract just variable names without types (which are hard to guess from Twig syntax), just for me to make sure that I have not overlooked some variables.
Also, it will be great if it would not declare variables created in the template, like this:
{# #var users AppBundle\Entity\User[] #}
{# "user" variable is not documented as it is not passed into the template from outside #}
{% for user in users %}
<p>Hello {{ user.fullName }}!</p>
{% endfor %}
Such comments are helpful not only for type hinting, but also for the developer to see what should be passed into the template when refactoring/reusing the template.
Thanks in advance.
As far as I can see there's unfortunately nothing that IDE or available plugins could suggest for your use case.
We are using Twig as our templating engine but I'm stuck with a problem of the rendering order now. See - https://straightupcraft.com/articles/twig-processing-order
We are using amp for our new site and with amp and web components in general it is necessary to import the components (once) to use them. So the idea was to create a Twig Extension to accomplish exactly this. Everytime a component is used it is called via this twig function call. The function is checking the component, adding it to a stack and you can use it from now on. The stack then is transformed into a list of imports for the head of the page.
The problem here is Twigs top to bottom rendering. When I call said function in a partial or a template the rendering of "layout.twig" already took place and all function calls below/after are not affecting the stack.
Is there an option to change the rendering to inside out, so that the rendering is first using the lowest partial and "bubbles" up to templates and finally layout without them rendering before?
Another way to get the values in layout would nice as well.
Desired behavior:
Layout.twig
{{ getAllComponents() }}
{# should output component1 and component2 #}
{% block content %}
Page.twig
{% extends Layout.twig %}
{{ addComponent('component1') }}
{% include partials.twig %}
<component1>...</component1>
partials.twig
{{ addComponent('component2') }}
<component2>...</component2>
Actual behavior:
Layout.twig
{{ getAllComponents() }}
{# is empty #}
There is no option to change this behavior. However you can use a trick to archive this:
Render your content to a variable before you call getAllComponents()
layout.twig
{% set mainContent %}
{% block content %}{% endblock %}
{% endset %}
{{ getAllComponents() }}
{{ mainContent }}
There actually is a magical solution to this problem -- some genius wrote this Deferred Twig Extension which lets you run some code (output a variable, call a function, etc) in a block near the top of your layout, but wait until the rest of the twig templates have parsed before executing them. There's an example on that github page showing how you can achieve this.
As far as I know, no you cannot switch the rendering of a TWIG template.
However, I would recommend possibly looking at the {% embed %} or {{ render }} tags.
Embed allows specific TWIG files to be placed within others with variables, so you could pass each component into their relevant partials.twig file.
Render allows the use of embedding a separate controller action, so you create a ControllerAction that took in a component variable and renders its own TWIG file.
Documentation on Embed: https://twig.sensiolabs.org/doc/2.x/tags/embed.html
Documentation containing Render: https://twig.sensiolabs.org/doc/2.x/api.html
I am using the node version of patternlab with twig as template engine. I am using twig because my codebase is written in twig - so using mustache it not an option.
I simple try to include an pattern:
<button type="button" class="btn {{ buttonClass }}">{{ cta }}</button>
in an other pattern with:
{% include "base-button" with {'buttonClass': 'btn-primary btn-xs'} %}
This does not work. The pattern is included but the variable buttonClass is not set.
Any Ideas?
This seems to be an issue with the twig integration in this repo https://github.com/pattern-lab/patternengine-node-twig.
There are other issues with twig core features described here: https://github.com/pattern-lab/patternlab-node/issues/554
I finally decided to switch to the php/twig edition and the same twig-patterns are working as expected. If anybody have to use the node edition, i recommend to use mustache.
I believe there are plans to pass the Twig rendering in Pattern Lab Node to PHP, however, this isn't ready yet, but using The Twig engine for Patternlab/Node you can pass a variable via an include. It doesn't work exactly the same as normal twig but it does work.
{% set buttonClass = 'btn-primary btn-xs' %}
{% include "components-button" with buttonClass %}
You can also pass multiple variables:
{% include "components-button" with buttonClass anotherVariable %}
I have installed VichUploaderBundle into my Symfony app and would like to have better control of the appearance of the upload buttons. I have taken the contents of fields.html.twig located in the bundle itself, and copied them into the same file at the path app/Resources/views/myControllerName/fields.html.twig This is also where all the other twig templates are for that set of controllers.
I can not seem to affect anything on the page through this method. Yes I have cleared the cache, I have even removed the cache directory.
Am I placing the file in the wrong place?
You can override that form theme in many ways, just when you customize vich_file_widget and/or vich_image_widget e.g.:
{% extends 'base.html.twig' %}
{% form_theme form _self %}
{% block vich_file_widget %}
{# some content… #}
{% endblock %}
{% block content %}
{{ form(my_form) }}
{% endblock %}
Thanks for the effort #jkucharovic, I was already using the 3rd method you were suggesting. My question was whether or not I put the fields.html.twig file in the correct place. Turns out I did not. For others that come along with this question, to override the fields file in the VichUploaderBundle for twig you must put a copy of the fields.html.twig file at the following path so that Symfony can override what comes with the bundle.
the fields file is found here and should not be edited...
vendor/vich/uploader-bundle/Resources/views/Form/fields.html.twig
a copy of that file should be placed here in Symfony 3. This file is editable.
app/Resources/VichUploaderBundle/views/Form/fields.html.twig