How can I loop on all items where a certain field is not empty? - jekyll

I want to loop over all items in a collection that have a certain field set (not empty). I tried this:
{% assign papers_with_demos=site.data.papers | where:"demo", not blank %}
{% if papers_with_demos.size > 0 %}
<h2>demos</h2>
{% for paper in papers_with_demos %}]
...
{% endfor %}
{% endif %}
but it does not work; all papers are returned.
My goal is that the heading "demos" will be shown, only if there is one or more paper with a demo.

If papers are being returned, you must be using data files. If a value is empty for a particular key in a data file it will return false. So you could check the data key with a forloop like:
{% for paper in site.data.papers %}
{% if paper.demo %}
something
{% endif %}
{% endfor %}
You'll find more info in the Data Files section of the Jekyll documentation.
Updated in response to your reply:
{% for item in site.data.items %}
{% if item.random %}
{% assign random-val = item.random %}
{% if random-val %}
<p>true</p>
{% endif %}
{% endif %}
{% endfor %}
This will return true if inside items.yml, you have - random: true, nothing if empty.

Related

For loop in Shopify not working over number 9

I'm having an issue with a for loop in Shopify. I'm sure it used to work, but I can't get it to work over the number 9 now.
{% assign productTag1 = Availability14 %} (in this example, the product has only 1 tag, which is Availability14)
{% assign avail_stop = false %}
{% for j in (0..15) %}
{% assign check_avail = 'Availability' | append:j %}
{% if productTag1 contains check_avail %}
{% assign avail_stop = true %}
{% capture tag_name %}{{check_avail}}{% endcapture %}
{% break %}
{% endif %}
{% endfor %}
{% if avail_stop %}
{% assign availability = check_avail | remove:'Availability' | plus:0 %}
{% endif %}
At the moment, I'm returning 1, not 14. I imagine it's something to do with the fact 14 includes a 1, but I can't wrap my head around it.
Any help is appreciated.
You have a {% break %} statement in your if. Once the if becomes true it will exit the loop instantly.
If you want to skip the next code you must use {% continue %} not {% break %}.
On my mind this is an issue with conditional operator. As you said, 14 contains 1, so why not simply use strict conditional operator like this:
{% if productTag1 == check_avail %}
{% assign has_stop = true %}
{% break %}
{% endif %}
(or did I miss something?)

Liquid/Jekyll: How to check for no posts when one has two or more conditions?

I am having trouble understanding how I might show a "no posts exist" message for a particular conditional statement with two variables.
In this example, let's say I have a collection of "animals" - on a particular page, I'd like a section that displays "primates that are herbivores":
{% for animal in site.animal %}
{% if animal.species == "primate" and animal.type == "herbivore" %}
{{ animal.content }}
{% endif %}
{% endfor %}
What I'd like to do is something like this (pseudocode):
{% if POSTS_EXIST_FOR_THIS_COMBO: (animal.species == "primate" and animal.type == "herbivore") %}
{% for animal in site.animal %}
{% if animal.species == "primate" and animal.type == "herbivore" %}
{{ animal.content }}
{% endif %}
{% endfor %}
{% else %}
There are no posts for this category.
{% endif %}
Note: This differs from examples like this, because I have two parameters to check. Can someone offer a suggestion about the syntax?
I think you can do the following where you at first filter all by species=primate from site.animal and then filter by type=herbivore from that pool and then check if the result exists.
{% assign animals = site.animal | where:"species","primate" | where:"type","herbivore" %}
{% if animals %}
{% for animal in animals %}
{{ animal.content }}
{% endfor %}
{% endif %}
Hope this helps.

Jinja & Wtforms- check if html attribute has been defined

Let's say I have a form with a hundred fields. Some of them have description defined:
i.e. Sales=IntegerField('Sales', description='Annual Sales')
some of them do not:
i.e. Name=TextField('Full Name')
in Jinja, how can I check whether description has been set or not?
I've tried
{% for field in form %}
{% if field.description != None %}
<h2>{{field.description}}</h2>
{{field.label}}
{{field}}
{% endif %}
{% endfor %}
I'm trying to iterate through the fields, and create an html header to group the fields into sections.
I was also doing
{%set currDesc="nothing"%}
{%for field in form %}
{% if field.description != currDesc %}
<h2>{{field.description}}</h2>
{% set currDesc= field.description %}
{% endif %}
{% endfor %}
but it ends up creating a ton of <h2>s
upon further research, we can check whether an attribute is defined explicitly in wtforms by using an empty string comparison:
{% if field.description =! '' %}
<h2>{{field.description}}</h2>
{% endif %}

jekyll: combine limit and where and reverse

Using Jekyll i'd like to:
iterate through all the pages
where the page.path is not the current path
where the page.categories contains "featured"
reverse them(most recent first)
limit 3
i'm having problems when getting all those filters together
{% assign posts = site.posts | reverse %}
{% for post in posts limit:3 %}
{% if post.categories contains 'featured' and post.path != page.path %}
{% include card.html post=post %}
{% endif %}
{% endfor %}
right now the limit is not working properly because the inner if will prevent a few items from being rendered.
Assign 0 to a counter variable before entering your loop. Don't set a limit on the loop, but instead set another condition on your counter being below your limit, and increment the counter using Liquid's plus filter every time you meet your criteria and output the card.
{% assign posts = site.posts | reverse %}
{% assign counter = 0 %}
{% for post in posts %}
{% if counter < 3 and post.categories contains 'featured' and post.path != page.path %}
{% include card.html post=post %}
{% assign counter = counter | plus: 1 %}
{% endif %}
{% endfor %}
A more complex example
I'm basing all of this on the looping I use myself. My condition is a little more complex: I check for any shared tag with the current page. I've included this as a further example below.
{% assign counter = 0 %}
{% for post in site.posts %}
{% if counter < 4 %}
{% if post.url != page.url %}
{% assign isValid = false %}
{% for page_tag in page.tags %}
{% for post_tag in post.tags %}
{% if post_tag == page_tag %}
{% assign isValid = true %}
{% endif %}
{% endfor %}
{% endfor %}
{% if isValid %}
{% include article_card.html %}
{% assign counter = counter | plus: 1 %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
Why where fails
Although Liquid has a where filter, it can only do exact comparisons, so you have to reinvent the wheel like this in order to achieve the where-like scenario for more complex conditions. This does make for a lot of looping through site.posts, but Jekyll being a preprocessor means the penalty of using a somewhat inefficient improvised where-type looping is only a compile-time concern, not a runtime one. Even so, to mitigate this cost as much as possible, I opt for having the counter condition be the first that Jekyll calculates.

Liquid markup sorting the output

I am trying to display a list of all articles using liquid markup. I've got this code which displays them properly, however I want to be able to sort by the modified date descending (most recent article on top). How can this be accomplished?
I was thinking that perhaps I need to create a new array with all articles in it and then sort that, but I am not sure how to do that. Also note that I want to sort ALL of my articles by date, not just within each folder.
{% for category in portal.solution_categories %}
{% if category.folders_count > 0 %}
{% for folder in category.folders %}
{% for article in folder.articles %}
{{ article.title }} - {{ article.modified_on | short_day_with_time }} <br>
{% endfor %}
{% endfor %}
{% endif %}
{% endfor %}
Thanks!
You can use a variable to sort the list of articles and then iterate that variable.
{% for category in portal.solution_categories %}
{% if category.folders_count > 0 %}
{% for folder in category.folders %}
{% assign sorted = (folder.articles | sort:date) %}
{% for article in sorted %}
{{ article.title }} - {{ article.modified_on | short_day_with_time }} <br>
{% endfor %}
{% endfor %}
{% endif %}
{% endfor %}