How to remove the maximum length of an array? - twig

I'm having some problems using twig.
When I try to bring an array to javascript, the array always returns the maximum length of 100.
i.e.
{% set getnumbers%}
{% for number in numberLists %}
{{number['odd'] | json_encode() }},
{% endfor%}
{% endset%}
var getNumbers = [
1,
3,
5 ...
197,
199
];
console.log (getNumbers);
On the console:
(100) [
1,
3,
5 ...
197,
199]
length: 100
Also
{{ numberLists | length }} returns = [100];
Although the length returns as 100, it is 100 numbers per page. the last number of the array should be 503.
I believe that the array is limited in some way due to the pagination that is set for every 100 elements.
this is the code for the pagination that is by default in the template
{% if pagination['count'] > 100 %}
{% if searchList %}
{% set params = {} %}
{% for search in searchList %}
{% set params = params | merge([search['name'] ~ '=' ~ search['value']]) %}
{% endfor %}
{% set params = '?' ~ params|join('&') %}
{% endif %}
I'm using a third-party system with an integrated API.
Unfortunately I don't have access to the back-end to be making any adjustments there, the only part I have access to, are the templates to configure some java, html and use some variables and arrays informed by the developer.
in the documentation provided by the developer, there is nothing relevant about this.
The dump function is appearing as unrecognized, from what I searched, it is not enabled by default, so it must be disabled.

Related

Check if all elements in one array are contained by another | JS Array.every() equivalent

I'm looping over a collection of blog posts (Twig for loop) which appearance depends on tags given.
Here a quick example: I want to display all blog posts that have the tags "foo" and "bar".
It seems pretty easy to check if a post has one of the tags.
However it seems that checking if both tags are contained by a blog post isn't trivial.
What I want to accomplish is what the array.every() method in javascript does.
That's my current solution which works as expected but feels kinda fiddly and overcomplicated:
{% set given_tags_array = data.tags|split(',') %}
{% for post in posts %}
{% set post_categories_array = post.categories|map(category => category.name) %}
{% set bool_buffer_array = [] %}
{# push comparison result in bool array #}
{% for tag in given_tags_array %}
{% set bool_buffer_array = bool_buffer_array|merge([tag in post_categories_array]) %}
{% endfor %}
{# only display posts where all tags match #}
{% if false in bool_buffer_array %}
{% else %}
{# post data goes here #}
{% endif %}
{% endfor %}
As you can see inside the posts loop I'm checking if every given tag (i.e. "foo" and "bar") is part of the post categories array. I'm pushing the comparison result (boolean) to an empty array to check for any false values afterwards.
Why an array? I tried using a simple boolean variable but if any of the given tags is in the post categories array it resolves to true, which isn't exactly what I want.
So something like that doesn't work for me unfortunately:
{% for post in posts %}
{% set post_categories_array = post.categories|map(category => category.name)|sort|join('') %}
{% if given_tags_array|filter(given_tag => given_tag in post_categories_array) %}
{# post data goes here #}
{% endif %}
{% endfor %}
With this method I'm always doing an or comparison instead of an and comparison...
So...am I missing something and is there a simpler way to do that twig only?
Using the code you've already provided:
{% set temp = given_tags_array|filter(given_tag => given_tag in post_categories_array) %}
The filter filter returns a new array, this means temp should contain as many elements as your given_tags_array, if they are all inside the post_categories_array.
So if I'm not mistaken you could change your check to the following
{% for post in posts %}
{% set post_categories_array = post.categories|map(category => category.name)|sort|join('') %}
{% set temp = given_tags_array|filter(given_tag => given_tag in post_categories_array) %}
{% if temp|length == given_tags_array|length %}
{# display post #}
{% endif %}
{% endfor %}

How to calculate the composite's elements and get total of them?

Hi I have a composite that has a QTY field and a TOTAL PRICE field and the table below would calculate and display the subtotal. It works properly when there is only one row of composite, but when I add more items, the subtotal field displays two subtotals instead of one as a whole. I want the subtotal field to display 24 instead of 4 and 20. How can twig solve this implementation? In my SUBTOTAL, I have
{% for item in data.item %}
{% set total_qty = (item.qty)|number_format(2,'.',',') %}
{% set per_price = (item.total)|number_format(2,'.',',') %}
{% set net_cost = (total_qty * per_price )|number_format(2,'.',',') %}
{{ net_cost }}
{% endfor %}
Here is the screenshot to give you better understanding
Don't output the net cost inside the for loop.
First create the sum, then display it after the loop.
Also don't use number_format before the final result.
{% set net_cost = 0 %}
{% for item in data.items %}
{% set net_cost = nest_cost + item.qty * item.total %}
{% endfor %}
{{ net_cost|number_format(2, '.', ',') }}
demo

Twig strip textarea and create array

I'm trying to strip some text from a value and afterwards create an array from it with the stripped values.
I'm having troubles to strip the text value.
I can only do this on the frontend since I have no access to the backend (SaaS platform)
In below example value.value (originally a textarea) returns the following text:
[185047078]1x something - Type 1
[415533322]1x something - something
[152890667]1x something 500x500 mm
I want to strip the text so I have [185047078], [415533322], [152890667] left or without the brackets.
Normally in JS you would do something like:
hide_ids = txt.match(/[^\]\[]+(?=\])/g)
However it need to be done in Twig.
Afterwards I want to push the values into an array hide_ids.
{% set hide_ids = [] %}
{% if product.custom %}
{% for custom in product.custom %}
{% if 'Some title' in custom.title %}
{% for value in custom.values %}
{% set hide_this_id = value.value %}
{% if hide_this_id matches '{/[^\]\[]+(?=\])/g}' %}
{% set hide_ids = hide_ids | merge([hide_this_id]) %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
{% set hidden = false %}
{% if id in hide_ids %}
{% set hidden = true %}
{% endif %}
What is the equivalent of match in Twig? I also tried replace but I just can't get that text stripped.
Any help greatly appreciated!
You could go with some simple string functions.
{% for id in ids %}
{{ id | split(']', 2)[0] | replace({'[': '',}) }}
{% endfor %}
demo
split is the explode of twig. This will separate your string in chased based on the ] character. The 2nd parameter (2) ensures there will only be maximum 2 parts in the array.
replace is just str_replace
If you wanted to solve this with regex you would either need to write a function/filter with preg_match or install an extension like this

Check in twig if at least on property exists in a given array

Let's assume I have an array $cars where $cars = [$toyota, $vw] and
$toyota= [
'id' => 1,
'color' => 'green',
];
$vw= [
'id' => 7,
'color' => 'red',
];
I wanna do a check in twig to see if at least one of the cars ID exists in a dedicated array ([3, ,7, 15]).
What's the best way to do this? Doing a for loop is not ideal since I cannot do a break if I found the first element matching my criteria. And I also don't wanna print a text twice if both elements satisfy the condition. I just want to print a text if one element does.
I tried doing something weird like
{% if cars in [3, 7, 15] %} .... {% endif %} but if obvously doesn't work since I need to check the id of a car, not the object...
Any suggestions on how to best solve this is much appreciated.
P.S. I know using array_filter in the controller makes it much easier, but sadly that doesn't work for me. That's because I use AJAX and after a submit, I won't have access to cars anymore. Therefore, I need to do it in the view..
You can do something like this (see https://twigfiddle.com/8u3eh5):
{% set found = false %}
{% for car in cars %}
{% if car.id in ids %}
{% set found = true %}
{% endif %}
{% endfor %}
{% if found %}
found
{% else %}
not found
{% endif %}
However, even if this is a working solution, you will be better off by implementing this in PHP code and expose such a function as a Twig test.
Just add a new filter to twig
$twig = new Twig_Environment($loader);
$twig->addFilter(new Twig_SimpleFilter('has', function($haystack, $needles) {
if (!is_array($needles)) $needles = [ $needles, ];
return count(array_intersect($haystack, $needles)) > 0;
});
Which you then can use like the following inside twig
{% set data = [ 'foo', 'bar', 'foobar', 'lorem', 'lipsum' ] %}
{% if data | has('foo') %}
data contains foo
{% endif %}
{% if data | has(['lorem', 'lipsum', 'boat']) %}
data contains lorem, lipsum or boat
{% endif %}

Counting the number of elements in array

I am looking to count the number of entries I have in an array in Twig. This is the code I've tried:
{%for nc in notcount%}
{{ nc|length }}
{%endfor%}
This however only produces the length of the string of one of the values in the array.
{{nc}} will produce an output of all the values of the array (there are 2) but I want the output to be just the number 2 (the count) and not all the information in the array.
Just use the length filter on the whole array. It works on more than just strings:
{{ notcount|length }}
This expands on the answer by Denis Bubnov.
I used this to find child values of array elements—namely if there was a anchor field in paragraphs on a Drupal 8 site to build a table of contents.
{% set count = 0 %}
{% for anchor in items %}
{% if anchor.content['#paragraph'].field_anchor_link.0.value %}
{% set count = count + 1 %}
{% endif %}
{% endfor %}
{% if count > 0 %}
--- build the toc here --
{% endif %}
Best practice of getting length is use length filter returns the number of items of a sequence or mapping, or the length of a string. For example: {{ notcount | length }}
But you can calculate count of elements in for loop. For example:
{% set count = 0 %}
{% for nc in notcount %}
{% set count = count + 1 %}
{% endfor %}
{{ count }}
This solution helps if you want to calculate count of elements by condition, for example you have a property name inside object and you want to calculate count of objects with not empty names:
{% set countNotEmpty = 0 %}
{% for nc in notcount if nc.name %}
{% set countNotEmpty = countNotEmpty + 1 %}
{% endfor %}
{{ countNotEmpty }}
Useful links:
length
set
for
{%for nc in notcount%}
{{ loop.index }}
{%endfor%}
loop.index -- The current iteration of the loop.
for reference:https://twig.symfony.com/doc/2.x/tags/for.html

Resources