Set a value on a multi level array - twig

dump(item.url.options.query)
returns: array (size=0)
{% set item = item|merge({'ref': 'xyz'}) %}
returns: no error, item is now set
{% set item.url.options.query = item.url.options.query|merge({'ref': 'xyz'}) %}
errors: Twig_Error_Syntax: Unexpected token 'punctuation'; of value '.'
How do I set the array index item.url.options.query?

You have a deeply nested array so you need to use the merge filter many times:
{% set item = item|merge({
url: item.urls|merge({
options: item.url.options|merge({
query: item.url.options.query|merge({
ref: 'xyz'
})
})
})
}) %}
If the item variable or some of the array items are objects instead of arrays, you might get an error (because the merge filter only works with arrays and Traversable objects), or the objects might get converted into arrays. If that's the case, you might want to take a look at the question DarkBee linked to.

Related

Twig multi dimensional array - Can't access values

I have a multidimensional array, but for some reason my twig is not responding with the array values.
Below is my twig Dump
array (size=2)
0 =>
object(App\Models\Entities\Strategy\CriticalSuccessFactor)[5]
private int 'csfId' => int 26
private iterable 'kpis' =>
array (size=1)
0 =>
object(App\Models\Entities\Strategy\KeyPerformanceIndicator)[10]
...
1 =>
object(App\Models\Entities\Strategy\CriticalSuccessFactor)[11]
private int 'csfId' => int 27
private iterable 'kpis' =>
array (size=1)
0 =>
object(App\Models\Entities\Strategy\KeyPerformanceIndicator)[12]
I did find this link, but it did not answer my question.
Multidimensional Array in Twig
Below is a respresentation of the array data I am working with
csfs[
private int 'csfId' => int 26
'kpis' => [
private int 'kpiId' => int 42
'objectives' => [
private int 'objectivesId' => int 40
]
]
]
when I am outputting the variable with twig I get nothing.
Here's my Twig:
{% for csf in csfs %}
{% for kpi in csf.kpis %}
<p> kpi ID : {{ kpi.kpiId }}</p>
{% endfor %}
{% endfor %}
{{ csf.csfId }} works. It prints the ID.
I can get the first array values no problem. But I cannot access kpis array
As seen in the documentation from twig,
For convenience’s sake foo.bar does the following things on the PHP
layer:
check if foo is an array and bar a valid element;
if not, and if foo is an object, check that bar is a valid property;
if not, and if foo is an object, check that bar is a valid method (even if bar is the constructor - use __construct() instead);
if not, and if foo is an object, check that getBar is a valid method;
if not, and if foo is an object, check that isBar is a valid method;
if not, and if foo is an object, check that hasBar is a valid method;
if not, return a null value.
Twig also supports a specific syntax for accessing items on PHP
arrays, foo['bar']:
check if foo is an array and bar a valid element;
if not, return a null value.
So you have two options here:
Adjust the model CriticalSuccessFactor
Either you could rename the method getKeyPerformanceIndicators to getKpis or add a method getKpis which just references getKeyPerformanceIndicators
public function getKpis() {
return $this->getKeyPerformanceIndicators();
}
Adjust your template and call the method getKeyPerformanceIndicatorsdirectly rather than let twig magically decide the method
{% for kpi in csf.getKeyPerformanceIndicators%}
...
{% endfor %}

A list as a message is converted to a string

I pass a list into a message using the django message framework. When it is rendered in the template, I try to access the list using {{ item.0 }} for example, but nothing is coming through. If I just use {{ item }}, I can see my list.
In short, I suspect the list isn't actually a list, it is a string that looks like a list (such as "['field1','field2']").
I arrive at this conclusion because if I try to access any list item > 0, the template renders empty, which implies there is no list item beyond position 0, which is consistent with the fact that item is a string.
Messages are populated in the View as:
for item in errorRecords:
messages.add_message(request, messages.WARNING, item)
Here, item is a list (e.g. ['field1','field2','field3']....)
Attempting to access the message list in the template:
{{ message.0 }}
works for position 0, but not for position 1 (renders blank). When access position 0, the entire list contents is shown . i.e. renders as:
['field1','field2','field3']
I want to be able to access each list's elements, so that I can populate a table with each field.

Accessing the referencing / parent element in twig (paragraphs)

I have an entity reference field inside a (parent-)paragraph, which references multiple child-paragraphs.
Is it possible to access field values of the referencing paragraph in the children's (referenced paragraph's) twig templates?
Actually I'm just trying to count the total referenced items within one of the referenced item's twig templates itself. So I want to count its siblings + 1, if you want.
I'm aware of the fact that I could preprocess this in a module, but I would like to know if this is possible in twig.
In twig:
{% set paragraph_parent = paragraph.getParentEntity() %}
{% set width = paragraph_parent.field_width.0.value %}
<div class="{{ width }}">{{ content.field_images }}</div>
Since there is no response to this question I have to assume that this is not possible in Twig, but wanted to quick share the mentioned workaround via module...
getParentEntity()
is your friend.
A short example for making the referenced element's count available...
/* implements hook_preprocess_paragraph() (paragraph type product_teaser) */
function mymodule_preprocess_paragraph__product_teaser(&$variables) {
/* makes paragraph siblings count (+ 1/self) available to template */
$siblings_total = 1;
$paragraph = $variables['paragraph'];
$parent_paragraph = $paragraph->getParentEntity();
if ( ( isset($parent_paragraph) ) && ( $parent_paragraph->hasField('field_paragraph_reference') ) ) {
$field_content = $parent_paragraph->get('field_paragraph_reference')->getValue();
if ( isset($field_content[0]['target_id']) ) {
$siblings_total = count($field_content);
}
}
$variables['mymodule_theming_sources']['siblings_total'] = $siblings_total;
}
Another method using twig with 2 simple lines. It works fine.
{% set parent = paragraph._referringItem.parent.parent.entity %}
{{ parent.title.value }}

Twig: Determine whether a menu item has a translation

In my Drupal 8 setup, I have two languages configured (German: default, English). Not all pages have a translation into English, but they show up in the navigation.
I'd like to highlight those menu items that link to pages that don't have a translation in the currently selected language.
So how can I do this in Twig? When I dump the menu item, I see an object of class MenuLinkContent that has a field entity which might contain the answer:
object(Drupal\menu_link_content\Plugin\Menu\MenuLinkContent)[31277]
[...]
protected 'entity' =>
object(Drupal\menu_link_content\Entity\MenuLinkContent)[31407]
[...]
protected 'translations' =>
array (size=2)
'x-default' =>
array (size=2)
...
'en' =>
array (size=2)
...
[...]
But I don't seem to be able to actually read those values.
It is easy, first, you have to add your current language to any variable by yourtheme_preprocess
yourtheme_preprocess(&$vars, $hook)
{
$language = \Drupal::languageManager()->getCurrentLanguage()->getId();
$vars['langcode'] = $language;
}
and now in your twig template, you have to check your entity if has a translation,
{% if node.hasTranslation(langcode) %}
{% set node = node.getTranslation(langcode) %}
{% endif %}

handlebars find and retrieve object based on other object iteration

i have an array holding objects from the server like this:
[Object, Object, Object, Object, Object]
so i'm doing an #each on that array, and i'm starting to display each value in the current object using the this keyword for example :
{{#if this.recommendations_received}}
{{this.recommendations_received.length}} recommendations
{{else}}
No recommendations
{{/if}}
each object has an id like so :
object : { id: "someid" ,
recommendations_received: [
{
recommendation_id: "some_ID",
giver: {
giver_id: "the_giver_id",
name: "the_giver_name"
}
}
]}
so i'm doing another iteration to show each recommendation like so:
{{#each this.recommendations_received}}
{{this.giver.name}}
{{/each}}
but now i need also to iterate over the giver categories array. which simply look like this
categories : [object, object, object]
inside each object in categories i have name and title.
i want to get the categories of the giver recommendation inside the #each helper that i did for recommendation_received based on the id of the giver which is unique.
You haven't shown how is giver and categories related to each, but you need to combine your objects before passing to handlebars. The easier way is to simply combine both objects by nesting the categories object inside the giver object. The other way would be to create a wrapper object to hold your main array and the categories array before passing to handlebars.

Resources