eleventy icon indicating copy to clipboard operation
eleventy copied to clipboard

How do you list all posts grouped by year?

Open logicman opened this issue 5 years ago • 5 comments

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!

logicman avatar Jun 24 '20 08:06 logicman

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!

logicman avatar Jun 24 '20 10:06 logicman

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

davidrhoden avatar Aug 05 '20 21:08 davidrhoden

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.

darekkay avatar Jan 31 '21 15:01 darekkay

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;
});

deerawan avatar Feb 01 '22 10:02 deerawan

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() });

sasrit avatar Jun 13 '22 21:06 sasrit