Preface
Goal: Miscellanous range loop to achieved wordpress like side panel widget.
Source Code
This article use tutor-07 theme. We will create it step by step.
5: Recent Posts
This require a new filter in main configuration.
Filter: Limit
Since nunjucks does not have a builty in function for limit.
We need to add limit
filter in .eleventy.js
:
// Limit Filter: Copy paste from Jérôme Coupé
eleventyConfig.addNunjucksFilter("limit", function(array, limit) {
return array.slice(0, limit);
});
Later you can use this filter as code below:
{% set posts = collections.posts | limit(5) %}
You can see how flexible nunjucks is.
Layout: Nunjucks Page or Post
Consider examine only recent posts:
<aside class="column is-one-thirds">
{% include "widget/recent-posts.njk" %}
</aside>
Partial Widget: Nunjucks Recent Post
{% extends "layouts/widget.njk" %}
{% set color = 'lime' %}
{% block widget_header %}
<strong>Recent Posts</strong>
<span class="fa fa-newspaper is-pulled-right"></span>
{% endblock %}
{% block widget_body %}
{% set posts = collections.posts | limit(5) %}
<ul class="widget-list">
{%- for post in posts -%}
<li><a href="{{ post.url | url }}">{{ post.data.title }}</a></li>
{%- endfor -%}
</ul>
{% endblock %}
The Loop
After sorting the posts array by date, I limit the result for only first five result.
{% set posts = collections.posts | limit(5) %}
<ul class="widget-list">
{%- for post in posts -%}
<li><a href="{{ post.url | url }}">{{ post.data.title }}</a></li>
{%- endfor -%}
</ul>
Render: Browser
You can open page
kind, or post
kind, to test this widget
.
6: Tags
Just a simple loop example.
Layout: Nunjucks Page or Post
Consider examine only tags:
<aside class="column is-one-thirds">
{% include "widget/tags.njk" %}
</aside>
Partial Widget: Nunjucks Recent Post
{% extends "layouts/widget.njk" %}
{% set color = 'light-blue' %}
{% block widget_header %}
<strong>Tags</strong>
<span class="fa fa-tag is-pulled-right"></span>
{% endblock %}
{% block widget_body %}
{%- for tag in collections.tagList -%}
{%- set tagUrl %}/tags/{{ tag | slug }}/{% endset -%}
<a class="tag is-small is-light
{{ color }} z-depth-1 hoverable p-b-5"
href="{{ tagUrl | url }}">
<span class="fa fa-tag"></span> {{ tag }}
</a>
{%- endfor -%}
<div class="clearfix"></div>
{% endblock %}
The Loop
This is actually, only a simple loop example, but with complex html formatting.
{%- for tag in collections.tagList -%}
{%- set tagUrl %}/tags/{{ tag | slug }}/{% endset -%}
<a class="tag is-small is-light
{{ color }} z-depth-1 hoverable p-b-5"
href="{{ tagUrl | url }}">
<span class="fa fa-tag"></span> {{ tag }}
</a>
{%- endfor -%}
Render: Browser
You can open page
kind, or post
kind, to test this widget
.
7: Grouped Archives
Making a grouping archive by month and year is not hard, it just need carefully carved with patient. Consider this step by step procedure to make this happened:
-
Grouping by Year
-
Grouping by Year, then Month
-
Give a Nice Formatting.
Filter: mapdate
We need previously discussed mapdate
filter,
to sort year
and month
.
// Custom: Grouping by date
eleventyConfig.addNunjucksFilter("mapdate", function(posts) {
return posts.map(post => ({
...post,
year: moment(post.date).format("Y"),
month: moment(post.date).format("MM"),
monthtext: moment(post.date).format("MMMM")
}));
});
You might want to read the article again.
Grouping by Year
This require two loops.
-
Year Loop, using
mapdate
Filter -
Posts Loop.
{% block widget_body %}
{% set posts = collections.posts %}
{% set page_year = page.date | date('Y') %}
{%- set posts = posts | mapdate -%}
{%- set groupByYear = posts | groupBy('year') | dictsort | reverse -%}
{%- for year, postsInYear in groupByYear -%}
{%- if year == page_year -%}
<ul class="widget-list">
{%- for post in postsInYear | sort(false, true, 'month') -%}
<li>
<a href="{{ post.url | url }}">
{{ post.data.title }}
</a>
</li>
{%- endfor -%}
</ul>
{%- endif -%}
{%- endfor -%}
{% endblock %}
Grouping by Year, then Month
This require three loops.
-
Year Loop, using
mapdate
Filter -
Month in Year Loop, using
mapdate
Filter -
Posts Loop.
{% extends "layouts/widget.njk" %}
{% set color = 'green' %}
{% block widget_header %}
<strong>Archive This Month</strong>
<span class="fa fa-archive is-pulled-right"></span>
{% endblock %}
{% block widget_body %}
{% set posts = collections.posts %}
{% set page_year = page.date | date('Y') %}
{% set page_month = page.date | date('MM') %}
{%- set posts = posts | mapdate -%}
{%- set groupByYear = posts | groupBy('year') | dictsort | reverse -%}
{%- for year, postsInYear in groupByYear -%}
{%- if year == page_year -%}
{%- set groupByMonth = postsInYear | groupBy('month') -%}
{%- set groupByMonth = groupByMonth | dictsort | reverse -%}
{%- for month, postsInMonth in groupByMonth -%}
{%- if month == page_month -%}
<ul class="widget-list">
{%- for post in postsInMonth | sort(false, true, 'month') -%}
<li>
<a href="{{ post.url | url }}">
{{ post.data.title }}
</a>
</li>
{%- endfor -%}
</ul>
{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endfor -%}
{% endblock %}
Give a Nice Formatting.
Each stuff should have their own header.
{% extends "layouts/widget.njk" %}
{% set color = 'green' %}
{% block widget_header %}
<strong>Archive</strong>
<span class="fa fa-archive is-pulled-right"></span>
{% endblock %}
{% block widget_body %}
{% set posts = collections.posts %}
{% set page_year = page.date | date('Y') %}
{% set page_month = page.date | date('MM') %}
{%- set posts = posts | mapdate -%}
{%- set groupByYear = posts | groupBy('year') | dictsort | reverse -%}
{%- for year, postsInYear in groupByYear -%}
<div class ="archive-year p-t-5" id="{{ year }}">
<a href="{{ "/pages/archives-by-month" | url }}#{{ year }}">
{{ year }}</a>
</div>
{%- if year == page_year -%}
{%- set groupByMonth = postsInYear | groupBy('month') -%}
{%- set groupByMonth = groupByMonth | dictsort | reverse -%}
<ul class="widget-archive m-t-0">
{%- for month, postsInMonth in groupByMonth -%}
<li class="list-month">
<span id="{{ year }}-{{ month }}">
<a href="{{ "/pages/archives-by-month" | url }}#{{ year }}-{{ month }}">
{{ month }}</a> - {{ year }}</span>
</li>
{%- if month == page_month -%}
<li>
<ul class="widget-list">
{%- for post in postsInMonth | sort(false, true, 'month') -%}
<li>
<a href="{{ post.url | url }}">
{{ post.data.title }}
</a>
</li>
{%- endfor -%}
</ul>
</li>
{%- endif -%}
{%- endfor -%}
</ul>
{%- endif -%}
{%- endfor -%}
{% endblock %}
This widget is specifically made for post
kind,
because we have already set date for each post
kind.
What is Next ?
Consider continue reading [ Eleventy - Widget - Data ]. We are going to explore eleventy static data feature with widget.
Thank you for reading.