Patternlab / Twig Variable Interpolation doesn't work with string from json - twig

I'm working on a project that's based on the twig patternlab framework. I'm using JSON files for most of my content, especially for pages.
I want to integrate a link (build by an atom) into a text I got from my JSON file that has a placeholder for the link. I'm working with texts from a multilingual cms so putting a placeholder into the text content is the easiest way to keep it flexible.
This is an excerpt from my json file
{
"legal" : "Mit dem Absenden des Formulars akzeptieren Sie unsere #{ legalLink }.",
"deeplink" : {
"label" : "Datenschutzbedingungen",
"url" : "#AGB_link"
}
}
and this is in my twig template
{# __ build the link __ #}
{% set legalLink %}
{% include "atoms-link" with contact.deeplink %}
{% endset %}
{# __ set up the string with interpolation placeholder __ #}
{% set legalText_a = "Mit dem Absenden des Formulars akzeptieren Sie unsere #{ legalLink }." %}
{% set legalText_b = contact.legal %}
{% set legalText_c %}
{% include contact.legal %}
{% endset %}
{# __ dump to check/debug how it comes out __ #}
{{ dump (legalText_a) }}<hr>
{{ dump (legalText_b) }}<hr>
{{ dump (legalText_c) }}<hr>
{# __ output the result __ #}
<p>A) {{ legalText_a|raw }}</p>
<p>B) {{ legalText_b|raw }}</p>
<p>C) {{ legalText_c|raw }}</p>
This is my result (both dump ant the final html.
string(121) "Mit dem Absenden des Formulars akzeptieren Sie unsere Datenschutzbedingungen ."
string(69) "Mit dem Absenden des Formulars akzeptieren Sie unsere #{ legalLink }."
object(Twig_Markup)#2627 (2) { ["content":protected]=> string(78) " Mit dem Absenden des Formulars akzeptieren Sie unsere #{ legalLink }. " ["charset":protected]=> string(5) "UTF-8" }
A) Mit dem Absenden des Formulars akzeptieren Sie unsere Datenschutzbedingungen.
B) Mit dem Absenden des Formulars akzeptieren Sie unsere #{ legalLink }.
C) Mit dem Absenden des Formulars akzeptieren Sie unsere #{ legalLink }.
Option A works perfectly, when I use twig set with a string, the interpolation kicks in and everything outputs correctly. But thats with a string in my template code... thats NOT what I want.
Option B was my first attempt with the String from my JSON file but when I use the var with a string for the set, the interpolation doesn't kick in. I tried multiple variations with |raw and not sure what else but the result was always the same.
Option C doesn't work either. Using twig set with the include as a chunk turns it into twig markup code and that can hardly be used for anything from my recent experience. I still thought I'd give it a try.
Is there a way to get the interpolation to work or is there a good alternative with twig/patternlab to get what I'm trying to achieve?

To solve this issue you would first need to enable the extension Twig_Extension_StringLoader. This give you access to the function template_from_string, which give you the ability to "create" templates inside twig and (re)enable the string interpolation you need.
register extension
$twig->addExtension(new Twig_Extension_StringLoader());
use template_from_string to achieve desired effect
{% set legalLink = 'Datenschutzbedingungen' %}
{{ include(template_from_string('{{ "'~contact.legal~'" }}')) }}

Related

Symfony3: how to invoke a custom twig function in a twig template? [duplicate]

I'm working on a project that's based on the twig patternlab framework. I'm using JSON files for most of my content, especially for pages.
I want to integrate a link (build by an atom) into a text I got from my JSON file that has a placeholder for the link. I'm working with texts from a multilingual cms so putting a placeholder into the text content is the easiest way to keep it flexible.
This is an excerpt from my json file
{
"legal" : "Mit dem Absenden des Formulars akzeptieren Sie unsere #{ legalLink }.",
"deeplink" : {
"label" : "Datenschutzbedingungen",
"url" : "#AGB_link"
}
}
and this is in my twig template
{# __ build the link __ #}
{% set legalLink %}
{% include "atoms-link" with contact.deeplink %}
{% endset %}
{# __ set up the string with interpolation placeholder __ #}
{% set legalText_a = "Mit dem Absenden des Formulars akzeptieren Sie unsere #{ legalLink }." %}
{% set legalText_b = contact.legal %}
{% set legalText_c %}
{% include contact.legal %}
{% endset %}
{# __ dump to check/debug how it comes out __ #}
{{ dump (legalText_a) }}<hr>
{{ dump (legalText_b) }}<hr>
{{ dump (legalText_c) }}<hr>
{# __ output the result __ #}
<p>A) {{ legalText_a|raw }}</p>
<p>B) {{ legalText_b|raw }}</p>
<p>C) {{ legalText_c|raw }}</p>
This is my result (both dump ant the final html.
string(121) "Mit dem Absenden des Formulars akzeptieren Sie unsere Datenschutzbedingungen ."
string(69) "Mit dem Absenden des Formulars akzeptieren Sie unsere #{ legalLink }."
object(Twig_Markup)#2627 (2) { ["content":protected]=> string(78) " Mit dem Absenden des Formulars akzeptieren Sie unsere #{ legalLink }. " ["charset":protected]=> string(5) "UTF-8" }
A) Mit dem Absenden des Formulars akzeptieren Sie unsere Datenschutzbedingungen.
B) Mit dem Absenden des Formulars akzeptieren Sie unsere #{ legalLink }.
C) Mit dem Absenden des Formulars akzeptieren Sie unsere #{ legalLink }.
Option A works perfectly, when I use twig set with a string, the interpolation kicks in and everything outputs correctly. But thats with a string in my template code... thats NOT what I want.
Option B was my first attempt with the String from my JSON file but when I use the var with a string for the set, the interpolation doesn't kick in. I tried multiple variations with |raw and not sure what else but the result was always the same.
Option C doesn't work either. Using twig set with the include as a chunk turns it into twig markup code and that can hardly be used for anything from my recent experience. I still thought I'd give it a try.
Is there a way to get the interpolation to work or is there a good alternative with twig/patternlab to get what I'm trying to achieve?
To solve this issue you would first need to enable the extension Twig_Extension_StringLoader. This give you access to the function template_from_string, which give you the ability to "create" templates inside twig and (re)enable the string interpolation you need.
register extension
$twig->addExtension(new Twig_Extension_StringLoader());
use template_from_string to achieve desired effect
{% set legalLink = 'Datenschutzbedingungen' %}
{{ include(template_from_string('{{ "'~contact.legal~'" }}')) }}

Does twig autoquote attributes?

I've found it weird to notice that assembling data-attributes as string and placing it on html node results in attribute value double quoted.
If i leave it unquoted:
{% set dataId = '' %}
{% if id is defined %}
{% set dataId = ' ' ~ 'data-id=' ~ id %}
{% endif %}
and put on html node:
<div class="testDiv"{{ dataId }}>
then the data-attribute is correctly quoted.
Is this reliable behavior of twig? Why does it work that way?
It turned out that the browser was fixing quotes for me. To be able to output parameters properly, one haz to:
Include quotes in the string:
{% set dataId = ' ' ~ 'data-id="' ~ id ~ '"' %}
And use raw filter to prevent escaping quote characters:
<div class="testDiv"{{ dataId | raw }}>

Twig: concatenate variable in string

I've just begun learning Twig and i'm really stuck at this stupid little issue. Concatenating this doesn't seem to work (eigenKleurInput will ultimately be a value):
{% set eigenKleurInput = "acefbf" %}
{% set customBackgroundColorInline = 'style=background-color: #' ~ eigenKleurInput %}
The output variable "customBackgroundColorInline" is put inside a div:
<section {{ customBackgroundColorInline }}>
Desired output would be
<section style="background-color: #xxx">
Thank you very much!
If I correctly understand your question the problem is about encoded character: if you add the " in your code twig render as ".
In this case you should use the raw filter as follow:
{% set eigenKleurInput = "acefbf" %}
{% set customBackgroundColorInline = 'style="background-color: #' ~ eigenKleurInput ~ '"' %}
<section {{ customBackgroundColorInline|raw }}>
So the output will be:
<section style="background-color: #acefbf">
You could try online in this working twigfiddle
Hope this help

Minus In twig block definition

What's the difference between this:
{%block body %}
and that
{%block body -%}
Just read something about it in the documentation, not sure if this will also apply on {% block ... %} tags.
Twig whitespace control
{% set value = 'no spaces' %}
{#- No leading/trailing whitespace -#}
{%- if true -%}
{{- value -}}
{%- endif -%}
{# output 'no spaces' #}
There's also another example given which trims the whitespace in front of the variable but doesnt't do it at the end - so the effect is only on one side.
{% set value = 'no spaces' %}
<li> {{- value }} </li>
{# outputs '<li>no spaces </li>' #}
The above sample shows the default whitespace control modifier, and how you can use it to remove whitespace around tags. Trimming space will consume all whitespace for that side of the tag. It is possible to use whitespace trimming on one side of a tag
So I think the difference in your given exmaples is that in the first block body there will be a whitespace after the block started. In your second example body - there's none after the block started.
Just read the documentation entry to see how it works.
EDIT
A simple example to demonstrate the example in the docu:
{% set value = 'NO space in source code after/before "value"' %}
<li> {{- value -}} </li>
...
outputs in Firebug in the HTML markup:
Whereas this
{% set value = 'space in source code after "value"' %}
<li> {{- value }} </li>
...
ouputs:
Notice the space between "value" and the closing </li> in the second example. So the minus - erases/trims a whitespace either before, after or on both sides of e.g. a variable.

Twig - Append string data to same variable

How would you append more data to the same variable in Twig? For example, this is what I'm trying to do in Twig:
var data = "foo";
data += 'bar';
I have figured out that ~ appends strings together in Twig. When I try {% set data ~ 'foo' %} I get an error in Twig.
The ~ operator does not perform assignment, which is the likely cause of the error.
Instead, you need to assign the appended string back to the variable:
{% set data = data ~ 'foo' %}
See also: How to combine two string in twig?
Displaying dynamically in twig
{% for Resp in test.TestRespuestasA %}
{% set name = "preg_A_" ~ Resp.id %}
{% set name_aux = "preg_A_comentario" ~ Resp.id %}
<li>{{ form_row(attribute(form, name)) }}</li>
{% endfor %}
You can also define a custom filter like Liquid's |append filter in your Twig instance which does the same thing.
$loader = new Twig_Loader_Filesystem('./path/to/views/dir');
$twig = new Twig_Environment($loader);
...
...
$twig->addFilter(new Twig_SimpleFilter('append', function($val, $append) {
return $val . $append;
}));
Resulting in the following markup:
{% set pants = 'I\'m wearing stretchy pants!' %}
{% set part2 = ' and they\'re friggin\' comfy!' %}
{% set pants = pants|append(part2) %}
{{ pants }}
{# result: I'm wearing stretchy pants! and they're friggin' comfy! #}
IMHO I find the above sample more intuitive than the ~ combinator, especially when working on a shared codebase where people new to the syntax might get a bit mixed up.

Resources