Gutenberg Blocks with Timber and ACF Flexible Content - twig

We're creating a block.twig template as per:
https://timber.github.io/docs/guides/gutenberg/#how-to-use-acf-blocks-with-timber
to use ACF Flexible Content Field Types to create Gutenberg Blocks.
For reference the following sample code would be for Repeater Field Types:
{% for field in fields.repeater %}
Title: {{ field.title }} <br/>
Url: {{ field.url }}
{% endfor %}
which we tested and seems to work fine.
What would be the equivalent using Flexible Content fields?
Thanks.

#Rafael they're a little more complicated, just need to handle them like arrays. Let's pretend your Flexible Content field is called my_fc_field inside of it. You created 2 layouts, each has a single text field, one called tf_one, the other fc_two
{% for subfield in fields.my_fc_field %}
Layout name: {{ subfield.acf_fc_layout }}
Text Field Value: {{ subfield.tf_one ? subfield.tf_one : subfield.tf_two }}
{% endfor %}
doing a {{ dump(fields.my_fc_field) }} should make it clear what's inside there that you can manipulate/output

Related

Shopware : Impossible to extend through plugin user-detail

I have Shopware 6.5.3. I was trying to extend "sw-users-permissions-user-detail" like this :
import template from './sw-users-permissions-user-detail.html.twig';
Shopware.Component.override('sw-users-permissions-user-detail', {
template
});
And file 'sw-users-permissions-user-detail.html.twig'
{% block sw_settings_user_detail %}
{% parent %}
{% block test %}
<p>Blabla</p>
{% endblock %}
{% endblock %}
It's not working at all, and I don't know why.
Any help ?
NB : It's working when I'm overriding other templates :
Component.override('sw-dashboard-index', {
template
});
If you want to put the original contents to the block, that you are overriding, you should use the 'parent' statement like this:
{{ parent() }}

What is the version of #component (from .blade) for twig file?

I don't know if this is right version of #component for twig? Is it render?
{{ render ('mail::message') }}
{{ render ('mail::button', ['url' => '']) }}
or maybe I am not able to write the right syntax here?
Check out Twig's macro.
For the Blade
<!-- /resources/views/demo.blade.php -->
{{ $slot }}
<!-- component use -->
#component('demo')
content
#endcomponent
the basic Twig syntax would be
{# macro definition #}
{% macro demo(param) %}
{{ param }}
{% endmacro %}
{# macro use #}
{# first import and then you can #}
{{ demo('content') }}
You'll need to import the macro before calling it, either with from or import. To import (with either from or import) from the current file, use _self instead of a path. See the docs for more explanation
Your example
{{ render ('mail::button', ['url' => '']) }}
looks like it's coming from Blade's #include, something like
#include('mail::button, ['url' => ''])
For that, Twig's include might be a better fit. The relationship between macros and includes in Twig is similar to the relationship between components and includes in Blade. The basic Twig would be
{# partial.html #}
{{ url }}
{# partial use #}
{% include 'partial.html' with {url: ''} %}

html_entity_decode for twig (opencart)

im trying to output an attribute of a product on my product page (opencart v3).
The attribute is called 'technicaldetails' and it works just fine using this code:
{% if attribute_groups %}
{% for attribute_group in attribute_groups %}
{% if attribute_group.name == 'technicaldetails' %}
{% for attribute in attribute_group.attribute %}
{{ attribute.text }}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
but the technical details field have unstyled list stored in it.. and this outputs the complete html instead of rendering the list.
ive tried using {{ attribute.text|e }} and {{ attribute.text|raw }} and many other alternatives i could find.. but each time is just throws out the html and not render it..
in php this used to work.
<?php echo html_entity_decode($attribute['text']); ?>
so how can i decode the html now as i cant use php in twig and there is no html_entity_decode in twig either :(
looking forward for somehelp :)
much appreciated
thanks.
Just register the html_entity_decode function in twig.
The most simple way is to look where twig is loaded and add the following code,
$twig->addFilter(new \Twig_Simple_Filter, 'html_entity_decode', 'html_entity_decode');
After that you can just do the following in your twig templates
{{ attribute.text|html_entity_decode }}
UPDATE: For Opencart 3.0.3.7 version filter should be like this:
$twig->addFilter(new \Twig\TwigFilter('html_entity_decode','html_entity_decode'));
Find file
document_root/system/library/template/twig.php
Just after
$this->twig = new \Twig_Environment($loader, $config);
add following code
$twig->addFilter(new \Twig_SimpleFilter('html_entity_decode', 'html_entity_decode'));
After doing this, you must went to admin to reload all modifications in menu Extensions -> modifications.
After that you can do the following in all twig files *.twig
{{ attribute.text|html_entity_decode }}

Symfony Translations

i'm using the last version of symfony (3.1.3)
i want to trans multi vars.
but i didn't find and good solution
right now i'm doing:
{% block h1 %}{{ 'service.create'|trans }} {{ ('service'|trans) }}{% endblock %}
I try :
{% block h1 %}{{ 'service','service.create'|trans }} }} { %endblock %}
but no luck.
I also try with
{% trans %}service.create|service{% endtrans %}
thanks
You can use parameters in your translation like this:
{{ 'service.create'|trans }}
{{ 'service.create'|trans({'%separator%': 'any text'}) }}
And in your messages.ru.yml
...
service:
create: ... %separator% ...
...
If your separator is in html, add raw like this :
{{ 'service.create'|trans({'%separator%': '<br>'})|raw }}
You have more details in symfony doc here
You can translate strings in backend:
public function indexAction($name)
{
$translated = $this->get('translator')->trans('Hello '.$name);
return new Response($translated);
}
Or in twig templates:
<h1>{{ 'service.create'|trans }}</h1>
Each time you create a new translation resource (or install a bundle that includes a translation resource), be sure to clear your cache so that Symfony can discover the new translation resources:
php bin/console cache:clear
More info: http://symfony.com/doc/current/translation.html
I needed to just trans multi vars.
twig not support that...
If you have a "service.yml.en" file or something like that :
{{ service.create|trans({}, "service") }}
Here the translator will search in your service.yml.en file and load the correct translation key.
If you want to do advance translations, you can use vars like that (for example) :
{{ (className|lower ~ "." ~ field)|trans({}, className|lower) }}
Here if you have a "user.yml.en" and you want to load something like "user.width", it'll work.
Good luck :)

Using twig variable to dynamically call an imported macro sub-function

I am attempting if use a variable to call a specific macro name.
I have a macros file that is being imported
{% import 'form-elements.html.twig' as forms %}
Now in that file there are all the form element macros: text, textarea, select, radio etc.
I have an array variable that gets passed in that has an elements in it:
$elements = array(
array(
'type'=>'text,
'value'=>'some value',
'atts'=>null,
),
array(
'type'=>'text,
'value'=>'some other value',
'atts'=>null,
),
);
{{ elements }}
what im trying to do is generate those elements from the macros. they work just fine when called by name:
{{ forms.text(element.0.name,element.0.value,element.0.atts) }}
However what i want to do is something like this:
{% for element in elements %}
{{ forms[element.type](element.name,element.value,element.atts) }}
{% endfor %}
I have tried the following all resulting in the same error:
{{ forms["'"..element.type.."'"](element.name,element.value,element.atts) }}
{{ forms.(element.type)(element.name,element.value,element.atts) }}
{{ forms.{element.type}(element.name,element.value,element.atts) }}
This unfortunately throws the following error:
Fatal error: Uncaught exception 'LogicException' with message 'Attribute "value" does not exist for Node "Twig_Node_Expression_GetAttr".' in Twig\Environment.php on line 541
Any help or advice on a solution or a better schema to use would be very helpful.
I just thought other people may want the answer to this, as provide by fabpot:
This is indeed something that is not supported: calling a macro with a dynamic name (I have added a proper exception to be clearer about the issue).
If you really want to do that, you can do so with the following code:
{{ attribute(forms, element.type, [element.name,element.value,element.atts]) }}
-fabpot
https://github.com/twigphp/Twig/issues/922#issuecomment-11133299
Dynamic macros may not be supported in Twig.
But there is a simple workaround since you can dynamically include other templates.
Example:
Let's say you have a bunch of content modules or content blocks (or however you wanna call them) for your site. And you have Twig macros responsible of rendering each of these modules.
{# modules.twig #}
{% macro module1(config) %}
<div>module one</div>
{% endmacro %}
{% macro module2(config) %}
<div>module two</div>
{% endmacro %}
{% macro module3(config) %}
<div>module three</div>
{% endmacro %}
Now, what you need to dynamically call these macros is to add an extra template for each, like so:
{# module1.twig #}
{% import "modules.twig" as modules %}
{{ modules.module1(config) }}
{# module2.twig #}
{% import "modules.twig" as modules %}
{{ modules.module2(config) }}
{# module3.twig #}
{% import "modules.twig" as modules %}
{{ modules.module3(config) }}
Finally, in your actual page template you just include the template instead of calling the macro.
{# template.twig #}
{# this is the macro's name to be called #}
{% set macro = 'module2' %}
{# this is just a config object to be passed to the macro #}
{% set config = {} %}
{% include macro ~ '.twig' with { config: config } only %}
Et voilá, (dynamically produced) output will be <div>module two</div>.

Resources