So I want to setup a for loop in Jekyll that only displays the latest event/item in the collection. (Organised by date)
Currently, this doesn't do much apart from sort the date by weight and cycle through the collection with a limit of one.
{% assign sorted_events = site.events | sort: "date" %}
{% for event in sorted_events limit:1 %}
<section class="venue-info wow fadeIn" data-wow-duration="1.2s" id="about">
<div class="upcoming-event">
<h1>Our Next Event</h1>
<h2>{{ event.title }}</h2>
<p>{{ event.description }}</p>
<a class="btn scroll" href="{{ event.url }}">Learn More</a>
</div>
{% endfor %}
Taking {{site.post}} as the collection for this example, we sort the collection of posts and then use the last tag to get the last element of the array.
To get the newest post:
{% assign newest = site.posts | sort: "date" | last %}
{{newest.title}}
{{newest.date}}
oldest post:
{% assign oldest = site.posts | sort: "date" | first %}
{{oldest.title}}
{{oldest.date}}
It should work for any other collection like site.events as your code refers.
Related
I'm trying to loop through all the collections that a set of products is part of. This is my code:
<div class="container model-collection">
<h1>{{ collection.title }}</h1>
{% paginate collection.products by 12 %}
<div class="grid collection-products-container">
<ul>
{% for product in collection.products %}
{% for collection in product.collections %}
<li>{{ collection.title }}</li>
{% endfor %}
{% endfor %}
</ul>
</div>
{% if paginate.pages > 1 %}
{% include 'pagination' %}
{% endif %}
{% endpaginate %}
</div>
This works fine, however if two products are part of the same collection it lists that collection twice. So I need to limit the loop that it only shows each collection once.
I've tried to do it like this:
<div class="container model-collection">
<h1>{{ collection.title }}</h1>
{% assign model = collection.title %}
<div class="grid collection-products-container">
<ul>
{% for product in collection.products %}
{% assign seen_collections = "" %}
{% for collection in product.collections %}
{% unless seen_collections contains collection %}
{% assign seen_collections = seen_collections | append: "," | append: collection %}
<li>{{ collection.title }}</li>
{% endunless %}
{% endfor %}
{% endfor %}
</ul>
</div>
</div>
But this only returns one of the collections twice and none of the others. Any ideas how to do this?
You can get an aggregate list of nested properties by using the map filter in your Liquid code, and the map filter lets you drill into nested objects quite efficiently.
So to get an array of all the unique collection handles used by all the products in your collection, we can quickly get the info we want as:
{% assign collection_handles = collection.products | map: 'collections' | map: 'handle' | uniq %}
This creates an array of all the collection handles of all the products inside the collection, then reduces them to just the unique ones (using the uniq filter). Note: uniq needs to work with a number, string, or other simple field - which is why we needed an array of collection handles, not an array of collection objects.
So now you can do your loop as:
{% for handle in collection_handles %}
{% assign collection = collections[handle] %}
<!-- All your awesome stuff here -->
{% endfor %}
Hope this helps!
As you see below, this is a fairly simple collection setup with an unordered lists of events that live in the _events folder at the root level (output is set to false). Instead of using {{ page.title }} in the layout, I want the heading(s) to read as months.
For example, if I add a new item into the _events collection and include month: January in the front-matter, I want that to generate a “January” heading, and place that unordered list underneath the heading. Likewise, if I add a new collection item and include month: February in the front-matter, I want to generate a “February” heading with a new unordered list below that heading.
I know I need a bit of re-arranging of where the heading lives, and I'm thinking I need some type of if statement, but I’m at a roadblock. I can’t figure this one out.
Is this possible with Jekyll Collections?
Layout
{% include root.html %}
<div class="flex-main">
{% include header.html %}
<main class="o-main" role="main">
<div class="o-grid-six">
<h1 class="f1 o-grid-six__child c-headline">{{ page.title }}</h1>
</div>
{{ content }}
</main>
</div>
<div class="flex-footer">
{% include footer.html %}
</div>
View (Events)
---
layout: events
title: Events
order: 2
---
<ul class="c-event-list">
{% for events in site.events %}
<li class="c-event-list__flag">
<div class="c-event-list__flag--left">
<div class="c-event-list__calendar">
<span class="c-event-list__day">{{ events.weekday }}</span>
<span class="f2 c-event-list__date">{{ events.date-number }}</span>
</div>
<img class="c-event-list__image" src="{{ p.url | prepend: site.baseurl }}{{ events.thumb }}" alt="">
</div>
<div class="c-event-list__flag--body">
<div class="c-event-list__content">
<h3 class="f2 c-event-list__title">{{ events.title }}</h3>
<p>{{ events.description }}</p>
<a class="c-button u-mt-2" href="{{ events.link }}">Sign Up</a>
</div>
</div>
</li>
{% endfor %}
</ul>
Collection item (an event)
---
layout: default
thumb: /images/event__screen-printing-basics.jpg
link: https://www.eventbrite.com/e/screen-printing-basics-tickets-41882948025
title: Screen Printing Basics
weekday: Wednesday
month: January
date-number: '10'
description: Join us for an after hours session to learn everything you need to know about screen printing in the Make Lab. We will be coating screens with emulsion, printing artwork onto transparencies, burning the image into the screen, washing out the stencil, mixing ink, prepping our work station, registering the paper, and finally pulling prints. The artwork always varies, so you’ll leave with a one-of-a-kind screen printed poster that you made yourself!
---
Interface
The best way to accomplish this is to use real dateTime and group_by_exp filter.
DateTime
---
layout: default
thumb: /images/event__screen-printing-basics.jpg
link: ...
title: Screen Printing Basics
description: ...
date: 2018-03-21 20:00
---
Note that for some reason date: 2018-03-21 doesn't work.
group_by_exp filter
Simplified print logic can be :
{% assign eventsByYear = site.events | group_by_exp:"event", "event.date | date: '%Y'" %}
{% for year in eventsByYear %}
<h1>{{ year.name }}</h1>
{% assign eventsByMonth = year.items | group_by_exp:"event", "event.date | date: '%B'" %}
{% for month in eventsByMonth %}
<h2>{{ month.name }}</h2>
<ul>
{% for event in month.items %}
<li>{{ event.title }}-{{ event.date | date: "%A, %B %d, %Y"}}</li>
{% endfor %}
</ul>
{% endfor %}
{% endfor %}
jekyll 2.4.0, Mac 10.12.5
{% for year_of_interest in (1997..2017) reversed %}
<large_year>{{year_of_interest}}</large_year>
{% for paper in site.data.publications | where,'site.data.publications.Year',year_of_interest %}
<div class="publication_card">
<a class="article_title" href="../../{{paper.Link}}" title="{{paper.Abstract}}">{{paper.Title}}</a>
</div>
<div class="paper_author_container">
<span class="paper_authors">{{paper.Author | upcase}}</span>
<br>
<span class="journal_info">{{paper.Year}}—{{paper.Journal | upcase}}</span>
<button class="btn" data-clipboard-text="{{paper.BibTex}}">
BIBTEX
</button>
</div>
{% endfor %}
{% endfor %}
The input CSV has this shape and the Year is a simple number:
Title,Link,Abstract,Author,BibTex,Year,Journal,SupplementalLink
background: I'm stuck! I have a CSV where each row represents publication metadata for papers from 1997 to 2016. Some years have many papers, but each year has at least 1 publication. I want a header for each year, and the publications to be posted below. Unfortunately, the where filter does not find any of the articles for a given year in the for loop.
Current functionality: under each header, it shows a list of ALL publications.
Desired: it should only show publications where the paper.Year == year_of_interest.
Thanks in advance!
Three problems here :
You can't filter in a loop
{% for paper in site.data.publications | where,'site.data.publications.Year', year_of_interest %}
Will not work as expected because it always returns all datas.
{% assign filtered = site.data.publications | where,'site.data.publications.Year', year_of_interest %}
{% for paper in filtered %}
Will work, but not now ...
Where filter filters on a key
It's not {% site.data.publications | where,'site.data.publications.Year', year_of_interest %}
but : {% site.data.publications | where,'Year', year_of_interest%}}
Nearly working ...
CSV datas are strings
{{ site.data.publications[0].Year | inspect }} returns "1987" and double quotes around signifies that its a string and that your filter, looking for an integer as "Year" value will never find it. You have to look for a string instead.
To cast an integer into a string you can append an empty string to it.
{% for year_of_interest in (1997..2017) reversed %}
{% comment %} casting an integer to a string {% endcomment %}
{% assign yearAsString = year_of_interest | append:"" %}
{% comment %} filtering datas {% endcomment %}
{% assign selectedEntries = site.data.publications | where: "Year", yearAsString %}
{% for paper in selectedEntries %}
Now, it does the job.
Notes :
1 - Use the | inspect filter to debug, it's useful to determine type of value (string, integer, array, hash).
2 - You can also cast a string to an integer by adding zero to it :
{% assign numberAsString = "1997" %}
{{ numberAsString | inspect }} => "1997"
{% assign numberAsInteger = numberAsString | plus: 0 %}
{{ numberAsInteger | inspect }} => 1997
This is the only documentation for the where filter because it is not a default liquid filter.
https://gist.github.com/smutnyleszek/9803727
site.data.publication.Year is an object of site.data.publications I believe you only need to specify "Year" This is case sensitive by the way.
{% for paper in site.data.publications | where, "Year", year_of_interest %}
I'm looking to display information from a csv file on a jekyll-generated site. I need to search for the appropriate category in the csv file, then display four of them on the page. Filtering to the selected category is no problem, but I'm having difficulty limiting the output to four.
Is there a way to apply a limit to an if statement? Or is there any other way to write this? I'm not that savvy in Liquid, so it's extremely likely that I'm missing an obvious solution.
Basic code to make all the applicable data show up on the screen:
{% for study in site.data.studies %}
{% if study.category contains "foo" %}
<div class="col-sm-3">
<h3>{{ study.title }}</h3>
<div class="list-of-attributes">
<h6>Attributes: </h6>
{{ study.attributes }}
</div>
</div>
{% else %}
{% continue %}
{% endif %}
{% endfor %}
I've also tried unless and tablerow, neither of which worked at all. Am I at least on the right track? How can I limit this forloop to stop at four items?
Thank you!
Ideally data should be filtered before rendering however you can also create a variable in liquid to hold the number of stuff rendered
{% assign rendered = 0 %}
{% for study in site.data.studies %}
{% if study.category contains "foo" %}
<div class="col-sm-3">
<h3>{{ study.title }}</h3>
<div class="list-of-attributes">
<h6>attributes: </h6>
{{ study.attributes }}
</div>
</div>
{% assign rendered = rendered | plus: 1 %}
{% if rendered == 4 %}
{% break %}
{% endif %}
{% endif %}
{% endfor %}
The ideal solution as I said would be to create your own filter which does all the work (filter by category and limit the number of results)
{% assign filtered = site.data.studies | my_custom_filter %}
{% for study in filtered %}
<div class="col-sm-3">
<h3>{{ study.title }}</h3>
<div class="list-of-attributes">
<h6>attributes: </h6>
{{ study.attributes }}
</div>
</div>
{% endfor %}
Presuming that your category is a string, not an array, you can do :
{% assign selected = site.data.studies | where: 'category','foo' %}
{% for study in selected limit:4 %}
<div class="col-sm-3">
<h3>{{ study.title }}</h3>
<div class="list-of-attributes">
<h6>Attributes: </h6>
{{ study.attributes }}
</div>
</div>
{% endfor %}
And if your category is a string like "foo, bar, baz" or and array of strings you can use the jekyll 3.2 where_exp filter like this :
{% assign selected = site.data.studies | where_exp:"item", "item.category contains 'foo'" %}
I'm looping through my collection of frontpage products and generating a table. In the last row, I need to put some static content in the first table cell. I've been able to do that, but for some reason, the loop stops after it does that. Does anyone know why?
{% tablerow product in collections.frontpage.products cols: 2 %}
{% if tablerowloop.col_first and tablerowloop.last %}
<img src="{{'box.png' | asset_url}}">
{% else %}
<div class='featured-product'>
<img src="{{ product.images[1] | product_img_url: 'medium' }}">
<p>{{ product.title }}</p>
</div>
{% endif %}
{% endtablerow %}
Here's the site: https://hodkiewicz-zieme-and-hirthe180.myshopify.com/
tablerowloop.last only returns true for the last cell of the table (i.e. last product of the collection), not for the last row. Instead you need to check if the index within cols of the end of the collection, such that it must be the last row if it is the first column.
{% tablerow product in collections.frontpage.products cols: 2 %}
{% assign x = tablerowloop.length | minus:2 %}
{% if tablerowloop.col_first and tablerowloop.index > x %}
<img src="{{'box.png' | asset_url}}">
{% else %}
<div class='featured-product'>
<img src="{{ product.images[1] | product_img_url: 'medium' }}">
<p>{{ product.title }}</p>
</div>
{% endif %}
{% endtablerow %}