Working with collections
Tue Jan 15 2019This post was written in 2019 for Eleventy 0.9.0. The general concepts are still valid, but the details may have changed.
Eleventy uses collections
to group posts
according to various criteria.
A collection might consist
of articles in a series.
Another collection could be
of posts about books.
A third could be
all the posts
in a particular directory.
Eleventy gives you two ways to create collections:
- implicitly, with tags in the front matter
- explicitly, with
addCollection()
Tag-based collections
Pages that share a tag
are in the same collection.
A template with the following front matter
would generate
pages in the collections
books
and reviews
.
---
title: Finding Oz
category: Culture
tags:
- books
- reviews
---
. . .
Within a template
collections are accessed
by name
as properties
of the global collections
object.
<p>
The title of this page is:
{{ collections.books[0].data.title }}
</p>
Collections are usually used in loops to iterate over each item in the collection.
{% for post in collections.books %}
{{ post.data.title }}
{{ post.url }}
{{ post.data.category }}
{{ post.data.tags }}
{{ post.date }}
{% endfor %}
The collections
object itself looks like this:
{
"all": [...],
"nav": [...],
"books": [
{
"inputPath": "./src/articles/finding-oz.md",
"outputPath": "_site/articles/finding-oz/index.html",
"fileSlug": "finding-oz",
"data": {...},
"date": "2009-08-07T13:52:12.000Z",
"url": "/articles/finding-oz/",
"templateContent": "<p>As with most books ... much about The Wizard of Oz</li>\n</ul>\n",
"template": {...}
},
...
],
"programming": [...],
}
Each property is an array of
collection item objects
(the doc also calls them
template objects).
The special collection all
is an array
of all of the page objects that Eleventy generates.
Property | Description |
---|---|
inputPath |
Path to this file including the input directory../src/articles/finding-oz.md |
outputPath |
Path to the rendered file.articles/finding-oz/index.html |
fileSlug |
Short name from the file name. There are rules. finding-oz |
data |
Data from the front matter of the rendered page. The global variables available to each page. |
date |
The date of this file in UTC. There are rules. 2009-08-07T13:52:12.000Z |
url |
Path to this content. Doesn’t include protocol or host. /articles/finding-oz/ |
templateContent |
The rendered content, not including any layout wrappers.<p>As with most books … much about The Wizard of Oz</p> |
template |
All sorts of data parsed out of the template. Things like the Eleventy configuration, markdown engine setup, and lots of stuff we probably shouldn’t rely on. |
Implementation: How a tag becomes a collection
Custom Collections
In addition to the collections
built from tags, you can
use addCollection()
in your
.eleventy.js
configuration file
to create your own collections.
For example, this is how to
create a collection called articles
made up of pages generated
from templates in the directory src/articles/
:
eleventyConfig.addCollection("articles",
collection => collection
.getAllSorted()
.filter(item => item.url
&& ! item.inputPath.includes('index.njk')
&& item.inputPath.startsWith('./src/articles/')))
addCollection()
takes two arguments:1
- the name of the collection (a string)
- a function that takes a
collection
as an argument.
addCollection(name, callback) {
name = this.getNamespacedName(name);
if (this.collections[name]) {
throw new UserConfigError(
`config.addCollection(${name}) already exists. Try a different name for your collection.`
);
}
this.collections[name] = callback;
}
You might think that the collection
parameter
is an array of template objects like the
tag-based collections
object.
Instead, this parameter is
an instance of a TemplateCollection
,
which is derived from Sortable
,
and
looks like this:
{
"items": [
{ ... },
. . .
{ ... }
],
"sortFunctionStringMap": { ... },
"sortAscending": true,
"sortNumeric": false
}
Its items
property
is an array of all the template objects.
It’s the same as collections.all
.
You don’t want to access the items directly
like this: collection.item[n]
.
Instead use the following methods
to get the items.
Method | Description |
---|---|
getAll() |
Gets all of the items in arbitrary order. |
getAllSorted() |
Gets all of the items in order. |
getFilteredByTag(tagName) |
Get all of the items with a specific tag. |
getFilteredByGlob(glob) |
Gets all of the items whose inputPath matches one or more glob patterns. |
The items are almost the same as the ones
in the tag-based collections.
In tag-based collections, items have templateContent
.
In addCollection()
collections, items have _pages
.
I don’t know why.
You can use addCollection()
to create
collections of pages. Since Eleventy 0.5.3,
you can use it to create collections
or arbitrary objects.
For instance, this is how you’d make a collection that consists of an array of all the category properties:
module.exports = function(collection) {
let catSet = new Set()
collection.getAllSorted().forEach(item =>
typeof item.data.category === "string"
&& catSet.add(item.data.category))
return [...catSet]
};
Implementation: How custom collections get built
addCollection()
doesn’t actually do anything other than to associate the collection-building function with the collection name. The collection-building function itself is called later ingetUserConfigCollectionsData()
. ↩︎