If twig replace isnt called, replace by nothing - twig

I want to give my users control over an input field via twig replace. So I created a var
<input type='text' %attr%>
Now with twig:
{{ var | replace({"%attr%":"id='12'"}) | raw}}
But if my users dont use replace, I dont want to display %attr% in the input field.
Is there a native twig way to do this?

As already commented, this is a bad design and it would be better to rethink your strategy. Anyhow a possible solution would be to write a custom filter and use that one over the raw filter.
By adding the option is_safe to the filter, the filter will behave exactly like raw, but you have more control over the end result.
In this case, you could replace %attr% if it hasn't been replaced by the filter replace before. You could even extend this list if needed be
$twig->addFilter(new \Twig\TwigFilter('safe', function($val) {
return str_replace([
'%attr%',
],[
'',
], $val);
}, ['is_safe' => ['html']]);
After you've added the filter to twig, you can use this filter anywhere:
{{ var | replace({"%attr%":"id='12'"}) | safe }}
{{ var | safe }}

Related

Is this the right way to implement my own filter in twig? (I want *minimal* whitespace between tags, not *no* whitespace between tags)

I know that apply spaceless "isn't about optimisation", in Symfony's words. But dammit, I dislike extraneous whitespace from being in my served files.
So I'm keen to use it.
But... I don't like how it reduces
<span>1</span>
<span>2</span>
to
<span>1</span><span>2</span>
As that results in the browser displaying 12, rather than 1 2.
In my mind whitespace between tags should be reduced to a single space, not to nothing.
<span>1</span>
<span>2</span>
->
<span>1</span> <span>2</span>
So I thought I'd make a custom filter, minimizeWhitespace, and wrap my templates with <% apply minimizeWhitespace %>
This is what I came up with:
function minimizeWhitespace($s)
{
return new \Twig\Markup(preg_replace('/\s+/', ' ', $s->__toString()), 'UTF-8');
}
$TWIG_env->addFilter(
new \Twig\TwigFilter('minimizeWhitespace', 'minimizeWhitespace')
);
This feels messy though - I'm taking their \Twig\Markup object, converting it to a string, running my regexp on it, and then creating a new \Twig\Markup object to return.
Is there a better way?

How to reference a Twig expression inside an expression

I'm trying to reference a Twig expression inside another expression:
{{ dbquery('name', 'product_manufacturer_translation', {'product_manufacturer_id =' lineItem.payload.manufacturerId} ) }}
Here, lineItem.payload.manufacturerId is the Twig expression I'm trying to put into the dbquery - but this does not work. Thanks for sharing your thoughts!
Edit: this query does not yield a result. What I would expect is a product manufacturer name, based on the product manufacturer ID. The manufacturerId experssion itself, when used on its own, does yield a result. I know there is a database record that should match this query, too.

Twig RAW filter on literal string not working

{{ (vendorData.description) ? vendorData.description : "<em>No Description Entered</em>"|raw }}
When the value is not present I see:
<em>No Description Entered</em>
Printed literally on the screen in the web browser.
Raw should force the characters to be literal, not > < etc.
Why does this not work on a "created string" but if I do it on a string variable it works?
You need to place brackets around the whole statement like so:
{{ ((vendorData)
? vendorData
: "<em>No Description Entered</em>")|raw }}
Here is a working twigfiddle to show it working:
https://twigfiddle.com/fs2oc2
You can use twigfiddle to experiment with your code.
From feedback in comments section:
here is a twig example to show what you need: https://twigfiddle.com/hjyslr

How not to escape path() in Twig Template

My objective is to render a Twig Template and send the resulting HTML via API to Mailchimp to be sent out.
My current process:
1) create a Twig-Template email.html.twig.
2) $html = $this->renderView('MyBundle:email.html.twig');
3) sendHtmlViaApi($html);
The issue:
I need a URL to contain a Mailchimp Merge Tag String, which has to be *|VARIABLE|*. I do that with {{ path('my_route', {variable : '*|VARIABLE|*'}) }}. The desired result: /myroute/*|VARIABLE|*. The result I get: /myroute/*%7CVARIABLE%7C*.
Already tried and failed methods:
1) using {% autoescape %}
2) |raw
3) Twig Extension with new url_decode Filter from Symfony2 Twig stop escaping path
So you want Twig to stop the automatic URL encoding.
You can pass a placeholder with only letters and underscore to path(), so that it won't be escaped. Then you can replace the placeholder with the string Mailchimp expect:
{{ path('my_route', {variable : 'MAILCHIMP_VARIABLE'})|replace({
'MAILCHIMP_VARIABLE': '*|VARIABLE|*'
}) }}
Thanks for your suggestions!
In the end it was all my own fault... One of the merge tags was missing on the mailchimp-side setup, so it couldn't replace it with the desired value.
Silly me!

In Twig, how do I use a dynamic key when translating

In my translation yml file I have these translations setup
pages:
training_missions:
...
application_name:
admin: "Admin Website"
mobile: "Mobile App"
kiosk: "Kiosk"
In my twig file, I need to set the application_name dynamically, but I can't get it to work properly.
This will translate fine, it gives me "Mobile App"
{{ 'pages.training_missions.application_name.mobile' | trans()}}
But this doesn't work, it gives me "pages.training_missions.application_name.mobile"
{{ 'pages.training_missions.application_name.'~trainingMission.application | trans() }}
edit:
The variable trainingMission.application contains one of the 3 strings I put in the yaml file : admin, mobile, kiosk
edit 2:
The solution is to wrap the string in parenthesis as per #Matteo 'Ingannatore' G. comment
It is possible! Use round brackets like this:
{{ ('pages.training_missions.application_name.'~trainingMission.application) | trans() }}
Use array accessor syntax:
{{ pages[training_missions].application_name.mobile }}

Resources