Check for paginate object in jinja2 - pagination

I have a page which receives a results objects and is supposed to iterate over it. results can be a paginate object, in which case the iteration would be
{% for data in results.items %}
or it can be a list in which case we would iterate as
{% for data in results %}
I am now trying to distinguish between the two cases with
{% if results.items %}
{% for data in results.items %}
// do something with data
{% endfor %}
{% else %}
{% for data in results %}
// do something with data
{% endfor %}
{% endif %}
however, in my case it can happen that results.items == 0, which would mean that the if statement is false. Therefore I need to have a way to check whether results.items exists, independent of the value it has. Does anybody know how to do this?

it was easier than I thought...
{% if not results or (results.items is defined and not results.items) %}

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 %}

Loop through entries within a category loop but only show once?

In a CraftCMs site I'm trying to loop through a couple categories, then loop through entries within each of those categories, but without duplicating the entry if it is in both categories.
Here's my base code:
{% set selectedCategories = craft.categories()
.id([12605, 12619])
.all()
%}
{% set articleAuthor = entry.id %}
{% for category in selectedCategories %}
{% set articles = craft.entries()
.section('articles')
.relatedTo([
'and', {articleAuthor}, {category}])
.all() %}
{% if articles %}
{% for article in articles %}
// entry data here
{% endfor %}
{% endif %}
{% endfor %}
This works, but if an entry is in both categories it shows in both sections. I want to limit it to showing in whatever may be the first listed section. What am I missing?
In this scenario you can create a variable and check whether a duplicate entry is found or not.
{% set existingIds = [] %}
{% for article in articles %}
{% if entry.id not in existingIds %}
{% set existingIds = existingIds|merge([entry.id]) %}
{% endif %}
{% endfor %}

How to render HTML to a variable

I need to render a list of HTML elements with content and put it into a variable. How can I do this efficient in twig?
e.g. I need to render the post tracking URLs from an order which can have several shippings / parcels.
{% for delivery in order.deliveries %}
{% for trackingCode in delivery.getTrackingCodes() %}
{{ trackingCode }}<br/>
{% endfor %}
{% endfor %}
Instead of printing this directly into the output I like first to put this rendered output into a variable like
{% set output = ... %}
...
{{ output }}
How can I do this in twig?
Just the concatenate the html to the output variable. Keep in mind you'll need to define to the variable outside the for-loop in order to use it outside the loop.
{% set foo = '' %}
{% for i in 1..10 %}
{% set foo = foo ~ ''~i~'' %}
{% endfor %}
{{ foo|raw }}
demo
After long search I found a better more efficient way
you can use {% set var %} with {% endset %} as a whole output block. Means the whole output will be set to the variable. This makes the life much easier and readable.
e.g.
{% set trackingText %}
{% for delivery in order.deliveries %}
{% for trackingCode in delivery.getTrackingCodes() %}
{{ trackingCode }}<br/>
{% endfor %}
{% endfor %}
{% endset %}
...
{% if trackingText|trim is not empty %}
You can track the delivery by using the following URL:<br/>
{{ trackingText }}
<br/>
{% endif %}

Laravel: Return a button if two columns in a table are true, if not, don' return anything

I need to loop through a table in .twig and if two columns are equal, it should return a button to delete., for example:
loop through boxes and if the quantity of boxes is equal to the available_quantity then I can show a delete button.
{% for toy in boxes.toys %}
{% if toy.quantity == toy.available_quantity %}
Delete
{% endif %}
{% endfor %}
Right now, this returns a button for each true case. I just need one button if all are true, if on or all are false I dont want a button
What you could do is something like this, as soon as you find a row where the quantities are different, set the value to false, so it'll never display the button:
{% set delete = true %}
{% for toy in boxes.toys %}
{% if toy.quantity != toy.available_quantity %}
{% set delete = false %}
{% endif %}
{% endfor %}
{% if delete %}
Delete
{% endif %}
Unfortunately Twig hasn't got a way to then break out of the loop, so it'll continue to loop over all the entries, but that won't be a problem.
Alternatively, you can use this method which will only loop over entries that match a certain condition, to do basically the same thing:
{% set delete = true %}
{% for toy in boxes.toys if toy.quantity != toy.available_quantity %}
{% set delete = false %}
{% endfor %}
{% if delete %}
Delete
{% endif %}
In this case, it'll only loop over the entries which have the values not matching, and in that case, set delete to false.
I came across a fix, not sure how ideal or correct this is. Im simply running the check inside the anchor tag and adding a hide class if quantities don't match up
<a href="" type="button" class="btn btn-xs btn-danger
{% for toy in boxes.toys %}
{% if toy.quantity != toy.available_quantity %}
hide
{% endif %}
{% endfor %}
">Delete</a>

Find needle within haystack in twig

I want to check whether a certain word exists in a string. However, there's not other operator that exists which can do the job except containment operator. The following doesn't work to my utter frustration.
{% set deduction = 'Less Withholding Tax Thereon' %}
{% if 'Witholding' in deduction %}
{% set test = "with" %}
{% else %}
{% set test = "out" %}
{% endif %}
{{ test }}
Please see fiddle with various tests all amounting to same result
https://twigfiddle.com/00odoi

Resources