eleventy
eleventy copied to clipboard
How do you list all posts grouped by year?
I am using the Eleventy-base-blog and on the archive page it lists all the posts in chronological order. This is the folder structure. All 2010 .md files are in the /posts/2010/ folder. And so on...
/posts/2010/ /posts/2011/ /posts/2012/ .....
The archived page works perfectly however, I want to group all 2010 posts together under the heading 2010. Then, all 2011 posts under 2011.....any idea how to achieve this or point me in the right direction?
Thanks!
It works and I think I got this one with some nunjucks code :) So, in my postlist.njk I wrote this:
<ol reversed>
{% set currentYear = "" %}
{% for post in postslist | reverse %}
{% if showYear %}
{% set postYear = post.date.getFullYear() %}
{% if currentYear != postYear %}
{% set currentYear = postYear %}
<h3>{{ postYear }}</h3>
{% endif %}
{% endif %}
<li class=" mb-10 list-none">
<h2><a href="{{ post.url | url }}">{% if post.data.title %}{{ post.data.title }}{% else %}<code>{{ post.url }}</code>{% endif %}</a></h2>
</li>
{% endfor %}
</ol>
And, in the archive.njk file I have this:
<h1>Blog</h1>
{% set showYear = true %}
{% set postslist = collections.posts %}
{% include "postslist.njk" %}
The output is:
2012 Blog post 1 Blog post 2
2011 Blog post 1 Blog post 2
2010 Blog post 1 Blog post 2
This way, my index.njk which also lists the latest 10 posts won't show the date as I don't have the showYear.
Is this the best way to achieve this?
Thanks!
I don't know if it's the best way, but it solved my issue nicely. What's the correct way to get data to a layout so I can do a "groupby" on it? #15
Another variant is described in #316
I came up with my own solution:
const _ = require("lodash");
eleventyConfig.addCollection("postsByYear", (collection) => {
return _.chain(collection.getAllSorted())
.groupBy((post) => post.date.getFullYear())
.toPairs()
.reverse()
.value();
});
{% for year, yearPosts in collections.postsByYear %}
<h2>{{ year }}</h2>
<ul>
{% for post in yearPosts | reverse %}
<li>{{ post.data.title }}</li>
{% endfor %}
</ul>
{% endfor %}
I have written a blog post with more explanation.
Based on @darekkay but without lodash
config.addCollection("postsByYear", (collection) => {
const posts = collection.getFilteredByTag('post').reverse();
const years = posts.map(post => post.date.getFullYear());
const uniqueYears = [...new Set(years)];
const postsByYear = uniqueYears.reduce((prev, year) => {
const filteredPosts = posts.filter(post => post.date.getFullYear() === year);
return [
...prev,
[year, filteredPosts]
]
}, []);
return postsByYear;
});
Hey everyone, I am currently using @darekkay s version and it works as intended, but I started to add multilingual support now. To sort by language I filter by folder. Is there a quick way to add a filter for a folder to that? Sorry, my javascript is too bad at the moment to figure that one out by myself, as I just started learning js. I guess I could create a folder for each year and get it this way, but there has to be a more sophisticated way to do that all at once, right?
my language filter atm:
eleventyConfig.addCollection("postsDE", function(collection) { return collection.getFilteredByGlob("./src/de/blog/**/*.md").filter((item) => { return !item.data.draft && item.date <= now; }).reverse() });