Limit number of entries in a list after its filtered - nunjucks

I have a list where I need to limit the number of entries that are already filtered by a tag. Since I need the limit to happen after the entries are filtered, I can't use " | limit(10)" as that only works in the for loop, not in the if statement.
The problem with limiting before filtering is that it only checks as many entries as the limit tells it to, so if there is no match in that number of entries, I get 0 entries as a result... which is not what I'm looking for, I need to first 10 entries that has the tag that I need to filter with.
This is what I have right now, entries show up, sorting works, filtering works:
---
pagecategory: 'potato'
---
{%- for review in collections.partner | sort(false, false, 'data.order_on_page') -%}
{% if review.data.tags.includes(pagecategory) %}
<p>{{review.data.title}}</p>
{% endif %}
{%- endfor -%}
entries can have multiple tags so I can't check for exact match to the 'pagecategory'.
I've searched the nunjucks documentation as well as all around the net, but I only found solutions that are the other way around - limiting the number of entries before they are filtered - that is not going to work.
How can I limit after filtering?

works if data.tags.includes() is a custom tag filter:
eleventyConfig.addFilter('filterByTag', (posts, tag) => posts.filter(p => p.data.tags.includes(tag)))
so theres no need for if statement:
{%- for review in collections.partner | filterByTag(pagecategory) | limit(settings.list_limit) | sort(false, false, 'data.order_on_page') -%}
<p>{{review.data.title}}</p>
{% endif %}
{%- endfor -%}

Related

Sorting in Jekyll / liquid code based on two columns

In my code I am trying to read about 100 yml files and create an html table. The problem I am facing is I am unable to sort based on two columns. The column names are vendor and name.
I need to first sort on Vendor and then name.
It sorts on one columns only the vendor column and ignore the next column name.. All the column names are correct.
This is the code.
{% assign devices = "" | split: " " %}
{% for device in site.data.devices %}
{% assign devices = devices | push: device[1] %}
{% endfor %}
{% assign sorted = devices | sort_natural: 'name' | sort_natural: 'vendor' %}
{% assign lastVendor = "" %}
{% assign nbDevices = 0 %}
{%- for device in sorted %}
{%- assign nbDevices = nbDevices | plus:'1' %}
{%- assign lastVendor = device.vendor %}`
Here i start creating the table which gets filled with values from the yml files.
The table when created is sorted on only one column. Either vendor or name.
Tried group_by as suggested here but then no values show up in the table not sure why.
Tried sort and sort_natural both the effect is the same.
Any suggestions as to what I am doing wrong here.
Finally figured out why the code was not working.
We were building our jekyll site using docker. The docker image was outdated.
A build using just bundle exec jekyll serve resolved the issue !!
Now need to update the bundler and gems....still figuring out what all gets updated and will post here in case it helps anyone.

Shopify Theme Development | Creating a 're-order' link for previous orders | Unable to chain multiple ID:quantity query strings

I am using Shopify and creating a re-order button within the file named order.liquid.
while trying to create the re-order button I have had a moderate level of success.
The script I attach does indeed add the items to the cart that were previously ordered. However, I have tried without adding the quantity (just adds 1 of each). Without the [] after the &quantityHERE= (just adds two of each even if it was previously only one item bought).
Heres the code that creates my half-working URL:
{% assign line_items_string = '/cart/' %}
{% for line_item in order.line_items %}
{% if forloop.first == true %}
{% assign line_items_string = line_items_string | append: 'add?id[]=' %}
{% assign line_items_string = line_items_string | append: line_item.variant_id %}
{% assign line_items_string = line_items_string | append: '&quantity[]=' %}
{% assign line_items_string = line_items_string | append: line_item.quantity %}
{% else %}
{% assign line_items_string = line_items_string | append: '&id[]=' %}
{% assign line_items_string = line_items_string | append: line_item.variant_id %}
{% assign line_items_string = line_items_string | append: '&quantity[]=' %}
{% assign line_items_string = line_items_string | append: line_item.quantity %}
{% endif %}
{% endfor %}
Re-order
I am unable to get it to add the correct amount of items per line item even though the URL appears correct:
/cart/add?id[]=16220586868785&quantity[]=3&id[]=16220587360305&quantity[]=6&id[]=16220587622449&quantity[]=4&id[]=16221376479281&quantity[]=11&id[]=16221376348209&quantity[]=2&id[]=16221063938097&quantity[]=1&id[]=16221393682481&quantity[]=2
The fact the string ends with quantity 2 and will then add 2 of each item suggests it only uses the last declaration of quantity when dealing with the link. Therefore there must be a separator that can be used to distinguish between line items.
What is the separator that would go between each line items addition to the query string please? What goes after?
add?id[]=16220586868785&quantity[]=3**HERE**
I have tried using a , but admittedly this looks out of place followed by an &.
Edit
To help describe further what I have tried.
I am able to use the format ID:quantity if I:
want to go straight to checkout, the format is ID:quantity,ID:quantity.. so on.
only wish to add one item of a certain quantity to cart using add?ID:Quantity.
I need to know how to chain multiple to only add to cart. I don't know the separator (that is a comma when pushing straight to checkout).
Using permalinks to re-order things is always the ID:quantity. Have you tried that?
I would consider implementing this using jquery or javascript. You can create an ajax post using the cart/add.js call described here: https://help.shopify.com/en/themes/development/getting-started/using-ajax-api#add-to-cart

and/or on a where_exp expression on Jekyll

I'm trying to use where_exp to filter Jekyll pages based on two categories using or operator:
{% assign sortedPages = site.pages | sort:"date" | reverse | where_exp:"page","page.categories contains 'design-pattern'" %}
But I'm getting this error:
Expected end_of_string but found pipe
Ar or/and operators really supported? I can't figure out how to filter pages using where_exp as shown in my code snippet.
I've managed to solve my issue with some workarounds... It's not a very elegant solution, but as Jekyll isn't about creating actual software architecture... For now, it works flawlessly:
{% assign patterns = "" | split,"" %}
{% for page in site.pages %}
{% if page.categories contains "design-pattern" or page.categories contains "anti-pattern" %}
{% assign patterns = patterns | push:page %}
{% endif %}
{% endfor %}
{% assign sortedPages = patterns | sort:"date" | reverse %}
I create an empty array.
I loop over all pages and I filter them by two possible categories.
I push pages that fulfill the whole condition.
Once I get the filtered page array, I sort and reverse it.
I was unable to replicate the error message you included with your original question. However, as far as filtering based on multiple conditions goes, it is supported. You can also put all of your filters together. The result is much cleaner code 😊
Example
If one wants to set a variable named "sortedPages" equal to "site.pages", but with the following filters:
Sort by date
Sort in reverse order
Only include a page if it has design-pattern and/or anti-pattern as a category
they can do so with the following one-liner:
{% assign sortedPages = site.pages | sort:"date" | reverse | where_exp: "item", "item.categories contains 'design-pattern' or item.categories contains 'anti-pattern'" %}
Answer as multiple lines
Splitting up statements across multiple lines is also supported. Doing so can sometimes improve readability:
{%
assign sortedPages = site.pages
| sort:"date"
| reverse
| where_exp: "item", "item.categories contains 'design-pattern' or item.categories contains 'anti-pattern'"
%}

Business Catalyst Liquid sorting

I can see that Liquid allows you to sort a collection using the below syntax:
{% assign sorted_items = items.all|sort:'Email' %}
{% for item in sorted_items %}
<div>Name: {{item.name}}</div>
<div>Email: {{item.email}}</div>
{% endfor %}
However this does not appear to work in Business Catalyst.
If I use this to render the result to the page it simply renders "null".
{{sorted_items | json }}
Should I be able to do this in Business Catalyst, or am I completely wasting my time trying to find a solution to sort my WebApp data?
You can sort the data like this:
{module_data resource="customers" version="v3" fields="firstName,email1" collection="myData"}
<pre>{{myData|json}}</pre>
{% capture emails -%}
{% for item in myData.items -%}
,{{ item.email1.value }} - {{ item.firstName }};
{% endfor %}
{% endcapture %}
<pre>{{ emails | split: "," | sort }}</pre>
The comma is not spelling mistake : )
After you split the string in array you can do whatever you need to do with it.
The answer from Daut is not good. Any solution in the for loop will only sort the number of items fetched from the module and the max amount for that is 500.
If you are using module_data you just use its actual sort!
{module_data resource="customers" version="v3" order="firstName" fields="firstName,email1" collection="myData"}
module_data supports both WHERE for filtering and ORDER to order the results.

How can I use Jinja2 to generate an index-like list?

In an index, references are listed alphabetically and grouped by letter. Also, instead of a simple alphabetical sort, leading articles and punctuation are removed before sorting. The result would look like this:
A
Abba
The Archer
Away From Here
B
"Bangkok" Mike
Bullets
I'm using the Pelican static site generator, which uses Jinja2 in its templates, and I'd like to create an index like this of TV shows that I've blogged about on my site.
TV show names are listed in a metadata field {{ article.showname }} (only one show per post, so only one show in the metadata field) and so are easily retrieved. But stripping the leading article/punctuation, grouping by first letter and inserting the correct letter of the alphabet is more than I know how to do.
Possible steps I could take
I could strip the leading article/punctuation and create another metadata field with the show name that's ready to be sorted, called, say, {{ article.shownamesort }}. For that matter, if there's not an easy way to group the names by their first letter, I could create a metadata field with the show's first (sortable) letter, {{ article.shownameletter }}.
For each letter, I could create a loop that begins by grabbing that letter's posts:
{% if article.shownameletter == "A" %}
Once that's done, I don't know how to sort the text from one metadata field based on the text of a different metadata field. That is, I don't know how to print the {{ article.showname }} list that's sorted by the {{ article.shownamesort }} list. Can this be done in Jinja2? For the record, if there's a solution that takes a completely different approach, I'd be very happy with it, including if it required different/more metadata fields.
I did something like that on the tags and categories pages. It iterates over all the characters and then prints the results
Iterate over the letters:
{% for char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"|list %}
...
{% endfor %}
Comparison for show or not show the tag:
{% if char == tag|upper|truncate(1, True, end='') %}
...
{% endif %}
Full example:
{% for char in "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"|list %}
<h2>{{char}}</h2>
{% for tag, articles in tags|sort %}
{% if char == tag|upper|truncate(1, True, end='') %}
<dt>{{ tag }}</dt>
{% for article in articles|sort %}
<dd>{{ article.title }}</dd>
{% endfor %}
{% endif %}
{% endfor %}
{% endfor %}

Resources