I want to automatically wrap some html, lets say <span data-id="..">
when I call {{ product.name }}
in my twig template.
So when in a twig template, I use {{ product.name }}
, I want the output to be: <span data-type="product" data-id="8" data-prop="name">My product name</span>
. I cannot use twig filters or macros, since I really need the template syntax to be {{ product.name }}
, so the end-user (template designer), does not have to care about it.
The reason I need this is because I am building an on-page editting tool for twig templates, so I need to know the contexts of those variables from within HTML.
I have tried to override the Compiler
that the Twig_Environment
uses, but I cannot seem to alter the output of the twig variable node.
How can I do this?
EDIT
I wanted to mention that I need this to use the {{ product.name }}
syntax, since other designers will work with those templates outside of Symfony 2. I want to make almost all twig variables editable in the front-end, so a solution with filters or macros can indeed work, but it kills the usability and readability of the platform I am writing. There is no public API currently in twig that can achieve what I want, that is why I am fiddling with the twig compiler. I do not have the required knowledge of the Twig internals to achieve this. If someone could point me into a direction that would be great!
UPDATE 2
I have found a place where I can achieve what I want. Every GetAttr
node is compiled to $this->getAttribute($someContext, "property")
. So if I can change the subclass of compiled twig template, I can achieve what I want. By default all twig templates extend from Twig_Template
. I want to extend this method.
How can I change the subclass of all compiled twig templates?
UPDATE 3
I've found a way to use my own base class for all compiled twig templates. I can simply set it as an option on the twig environment, see this link. I hope to get it working tomorrow and I will post a proper answer on how I solved it all together. Not sure how I will handle escaping, since that will happen after the $this->getAttribute()
is called.
I think macros are the best candidates for those kind of wrappings.
For example:
main.twig
{% import "macros.twig" as macros %}
{{ macros.display_product(product) }}
macros.twig
{% macro display_product(product) %}
<span data-id="{{ product.id }}" data-prop="name">{{ product.name }}</span>
{% endmacro %}
Context
product:
id: 8
name: My Georgeous Product
Result
<span data-id="8" data-prop="name">My Georgeous Product</span>
See fiddle
I've solved it by wrapping the PrintNode
that is created when parsing a VAR_START
token (inside the twig parser) with my own EditablePrintNode
. In that node I traverse the expression that is compiled by the print node and get the necessary property path and pass that as an argument to a wrapper function around the default twig escape function that is compiled by the PrintNode
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With