Closed brycewray closed 4 years ago
@brycewray Sorry, I haven't used 11ty.js templates so this might not be the best approach (I usually channel @reubenlillie's excellent https://gitlab.com/reubenlillie/reubenlillie.com site for 11ty template inspiration), but curious if something like this might work:
I didn't have a collection or something handy, so I created a src/_data/users.js file that I paginated and then set dynamic permalinks+nav.
But I think that correctly sets the ARIA props for the nav:
<main>
<h2>Hello Earl!</h2>
<nav>
<ul>
<li><a href="/cast/">Page 1</a></li>
<li><a href="/cast/2/">Page 2</a></li>
<li><a href="/cast/3/" aria-current="page">Page 3</a></li>
</ul>
</nav>
</main>
<footer>nav</footer>
If you build the site, you should get an output directory like this:
tree www/
www/
├── cast/
│ ├── index.html
│ ├── 2/
│ │ └── index.html
│ └── 3/
│ └── index.html
└── pages
└── index.html
4 directories, 4 files
@pdehaan Thanks! Have been following the @reubenlillie repo as well (excellent, indeed), but didn’t find any pagination happening there, hence my cry for help. :) Will give your suggestion a try.
@pdehaan On my first attempt to run this (after minimally altering the user
-related things to be post
-related), got an error message that pageEntry
is undefined, and that does square with the color-coding I'm seeing in VS Code. Where does pageEntry
come from?
pageEntry
was just the arbitrary variable name in my .map()
loop:
render(data) {
const nav = data.pagination.pages.map((pageEntry, idx) => {
const href = data.pagination.hrefs[idx];
const ariaCurrent = data.page.url === data.pagination.hrefs[idx] ? `aria-current="page"` : "";
return `<li><a href="${ href }" ${ariaCurrent}>Page ${ idx + 1 }</a></li>`;
}).join("");
const userString = data.user.map(user => user.name);
return `<h2>Hello ${userString.join(" and ")}!</h2><nav><ul>${ nav }</ul></nav>`;
}
Is your repo public? Might be easier if I clone your repo and look at your code.
Thanks again!
After further tinkering, think I've decided to concede defeat and continue letting the posts list template be Nunjucks. Also, wasn't able to figure out how to translate Max Böck's amazingly effective webmentions code from Nunjucks to .11ty.js, so am going to return to using Talkyard for commenting. Still, the other pages will now be .11ty.js-based. Perhaps in time I'll learn enough to go fully .11ty.js-based, but for now this will have to do. I did notice a tweet from @reubenlillie saying even he still has a smidge of non-.11ty.js-based templating in his site (although he's working on resolving that), so that makes me feel slightly better. 😃
@brycewray and @pdehaan,
First of all, thank you for your patience with me chiming in here. Second, thank you for your repeated kind endorsements about my site. (I’m still figuring out “best practices” for *.11ty.js
-style Eleventy, but I’m glad it’s been helpful to you.)
Now, I was able to make this snippet of a chained archive layout based on the Nunjucks example in the docs using previous–next navigation.
// _includes/layouts/archive.11ty.js
/**
* @file Defines the chained template for a collection archive page
* @author Reuben L. Lillie <reubenlillie@gmail.com>
* @see {@link https://www.11ty.dev/docs/layouts/#layout-chaining Layout chaining in 11ty}
* @see {@link https://www.11ty.dev/docs/pagination/#paging-a-collection Paging a collection in 11ty}
*/
/**
* Acts as front matter in JavaScript templates
*/
exports.data = {
layout: 'layouts/base'
}
/**
* The content of the template
* @method
* @name render()
* @param {Object} data 11ty’s data object
* @return {String} HTML template literal
* @see {@link https://www.11ty.dev/docs/pagination/ Pagination in 11ty}
*/
exports.render = function (data) {
return `<header>
<h2>${data.title}</h2>
</header>
${data.content}
<section id="archive">
<ul>
${data.pagination.items.map(function (item) {
return `<li>
<a href="${item.data.page.url}">${item.data.title}</a>
</li>`
}).join('')
}
</ul>
<nav aria-labelledby="pagination">
<h2 id="pagination" hidden>Pagination</h2>
${data.pagination.href.previous
? `<a href="${data.pagination.href.previous}">
${data.pagination.reverse
? 'Previous'
: 'Next'
}
</a>`
: ''
}
${data.pagination.href.next
? `<a href="${data.pagination.href.next}">
${data.pagination.reverse
? 'Next'
: 'Previous'
}
</a>`
: ''
}
</nav>
</section>`
}
Then, as far as the Nunjucks example for pagination navigation which @brycewray mentioned above, the crucial detail is that data.pagination.pages
is an array. So, I would actually reach for Array.prototype.map()
with the optional index
parameter in the callback (i.e., loop.index0
in Nunjucks, so I’ve learned) instead of a for...in
loop as in Nunjucks (see Array.prototype.map()
in MDN):
/**
* Eleventy pagination navigation starter example
* translated from Nunjucks to vanilla JavaScript
* @see {@link https://www.11ty.dev/docs/pagination/nav/#starter-example 11ty docs}
*/
exports.render = function (data) {
return `<nav aria-labelledby="my-pagination">
<h2 id="my-pagination">This is my Pagination</h2>
<ol>
${data.pagination.pages.map(function (item, index) {
return `<li>
<a href="${data.pagination.hrefs[index]}"
${data.pagination.hrefs[index]
? 'aria-current="page"'
: ''
}>Page ${index + 1}</a>
</li>`
}).join('')}
</ol>
</nav>`
}
@pdehaan, you bring up a good (related?) stylistic point. Is caching variables that are only used once in a given return
statement better for readability and/or performance, especially for newcomers to *.11ty.js
? In other words, is a list of variables followed by a pithy return
statement easier to read or faster than a longer, top-to-bottom return
statement? Or is it simply a matter of taste? (PS, I still think taste is important.)
@reubenlillie @pdehaan As I noted on Twitter, I decided to revert to all-.njk templating (and webmentions) for now since that better fits my limited skill set, but I remain intrigued by the potential advantages of an all-.11ty.js approach. Perhaps someday, someone will have time to flesh out the official Eleventy docs for each of the supported templating languages rather than just supplying intriguing examples for some of them — notably Nunjucks and Liquid, it would seem. That would be incredibly helpful for folks like me who find an all-JS approach a wonderful concept but lack (in my case) the training and expertise to make it roll.
@brycewray, that settles it. I am resolved, with blessing from @zachleat, to translate more examples in the docs into JavaScript. And, if you're looking for recommendations to dig into vanilla JavaScript, I cannot speak too highly about the stuff @cferdinandi publishes.
… the stuff @cferdinandi publishes.
Being at https://gomakethings.com/ and sundry URLs referenced within that realm.
@brycewray, that settles it. I am resolved, with blessing from @zachleat, to translate more examples in the docs into JavaScript. And, if you're looking for recommendations to dig into vanilla JavaScript, I cannot speak too highly about the stuff @cferdinandi publishes.
Thanks for that (and for the subsequent link you provided)! I have also found https://eloquentjavascript.net to be extraordinarily helpful, although it obviously requires more free time than one might have, especially when the need is simply to find a quick answer to “Aw, man, now how do I do that?” without risking the ego deflation that comes from asking a question on Stack Overflow that is remotely similar to something somebody asked eons ago. :)
@brycewray, yes—that self-respecting reference is https://vanillajstoolkit.com/ by @cferdinandi, followed by https://gomakethings.com/search/.
For what is worth, here is how I've solved it:
index.11ty.js
module.exports = class IndexPage {
data() {
return {
pagination: {
size: 1,
data: 'data', // <== This comes from `index.11tydata.js`
alias: 'entry',
},
permalink: (ctx) => {
return {
ca: '/',
es: '/es/',
}[ctx.entry.locale];
},
};
}
render(ctx) {
// console.log(ctx); // <== Uncomment this to get a better idea of what is happening
return `Index: ${ctx.entry.locale}`;
}
};
index.11tydata.js
module.exports = async function () {
return {
data: [ // <== Add `data` entry to global context
{ locale: 'ca' },
{ locale: 'es' },
],
};
};
The pagination examples are excellent for Nunjucks and Liquid, but translating them to .11ty.js form is beyond me. My use case is listing my site's posts. I am using the prescribed way of handling the front matter (desired result is pagination with a reverse-order list of posts, five listed per page)...
...but can't quite get anywhere from there. I can make a list of all the pages readily enough, but quite frankly am not JS-savvy enough to translate these items (shown below) from the "Put it all together" example from Nunjucks to .11ty.js:
Any thoughts, anyone? And feel free to chide me on my JS ignorance. :-)