I have the following two blocks of code in my .eleventy.js
file
// Tags
eleventyConfig.addCollection('tagList', collection => {
const tagsSet = new Set();
collection.getAll().forEach(item => {
if (!item.data.tags) return;
item.data.tags.filter(tag => !['posts', 'all'].includes(tag)).forEach(tag => tagsSet.add(tag));
});
return Array.from(tagsSet).sort();
});
// Categories
eleventyConfig.addCollection('categoryList', collection => {
let catSet = new Set();
collection.getAll().forEach(item => {
if (!item.data.categories) return;
item.data.categories.filter(cat => !['posts', 'all'].includes(cat)).forEach(cat => catSet.add(cat));
});
return Array.from(catSet).sort();
});
In my posts I Have
---
layout: post
title: 'Whatever'
date: '2021-10-12'
permalink: '{{ title | slug }}/index.html'
categories:
- code
tags:
- javascript
- angular
---
And i'm using a template like this to auto generate pages for each Tag (and a similar one for categories).
---
layout: page
eleventyComputed:
title: All posts tagged '{{ tag }}'
permalink: /tags/{{ tag }}/
pagination:
data: collections
size: 1
alias: tag
filter:
- all
- nav
- post
- posts
- tagList
addAllPagesToCollections: true
permalink: /tags/{{ tag }}/
headerButton:
url: '/blog/'
text: All posts
---
<ul class="unstyled">
{%- for post in collections[tag].reverse() -%}
{%- if not post.data.draft -%}
<li>{% include 'post-listing.njk' %}</li>
{%- endif -%}
{%- endfor -%}
</ul>
For tags, everything is working fine. I get the correct pages generated i.e. /tags/javascript
but for categories, its generating pages based on the Tags and not the categories. So instead of /categories/code
I'm ending up with /categories/javascript
I'm assuming the issue is with my eleventyConfig.addCollection('categoryList')
function but I have no idea why.
Your issue might be in the pagination in your template. You're paginating on the collections
object, which is an object mapping tags (a special 11ty front matter attribute) to pages with that tag.
Since you're creating a list of tags and categories as collection items, you'll want to paginate that collection instead.
---
# ...
pagination:
data: collections.tagList # (or collections.categoryList)
size: 1
alias: tag
# ...
---
This might pose an issue since you're accessing the posts themselves in the template, so you need a way to map the tag/category back to the list of posts. You can fix this by changing your collections to an Object
instead of an Array
.
// Tags
eleventyConfig.addCollection('tagList', collection => {
const tagsSet = {};
collection.getAll().forEach(item => {
if (!item.data.tags) return;
item.data.tags.filter(
tag => !['posts', 'all'].includes(tag)
).forEach(
tag => {
if (!tagsSet[tag]) { tagsSet[tag] = []; }
tagsSet[tag].push(item)
}
);
});
return tagsSet;
});
// Categories
eleventyConfig.addCollection('categoryList', collection => {
let catSet = {};
collection.getAll().forEach(item => {
if (!item.data.categories) return;
item.data.categories.filter(
cat => !['posts', 'all'].includes(cat)
).forEach(
cat => {
if (!catSet[cat]) { catSet[cat] = []; }
catSet[cat].push(item)
}
);
});
return catSet;
});
Now, when you want to access the posts, you can index into collections.tagList
(or collections.categoryList
).
{%- for post in collections.tagList[tag] | reverse -%}