Paginating Global Data #2831
-
Hi guys, just need a little help with generating pages via global data json file. I've got something like this in a stock.json file in my _data folder ... [
{
"brand": "Audi",
"tags": [
"audi",
"used",
],
"stock": [
{
"Range": "TT",
"Model": "40 TFSI Sport",
"Derivative": "40 TFSI Sport 2dr S Tronic",
"Price": "27,950"
},
{
"Range": "e-tron",
"Model": "300kw 55 Quattro Technik",
"Derivative": "300kW 55 Quattro 95kWh Technik 5dr Auto"
}
]
},
{
"brand": "BMW",
"tags": [
"bmw",
"used",
],
"stock": [
{
"range": "1 Series",
"model": "M140i Shadow Edition",
"derivative": "M140i Shadow Edition 5dr Step Auto",
},
]
}
] In the above json example uou can see that there are a couple layers to the json file, and I would like to paginate on each brands stock array. My pagination nunjucks file looks like this, as per the eleventy docs: pagination:
data: stock
size: 1
alias: vehicle
permalink: "/search/{{ vehicle.brand | slugify }}/{{ vehicle.stock.range }}/{{ vehicle.stock.model | slugify }}/"
My problem is the output is correct (depending on the pagination data value), but only for the first vehicle in the stock array. Does the pagination only iterate on the first level of json file? What I would like to end up with is ... /audi/tt/40-tfsi-sport Apart from restructuring the json file, is there anyway to iterate over both brand and stock levels using pagination? I could create a template file for each brand, and then individually point the pagination data directly to the 2nd layer stock array, but that seems inefficient when I could potentially do it all programatically? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 13 replies
-
I think if you search the issues for "pagination" there should be a few threads for double-pagination or multi-pagination which might have some ideas. I did find #332 In your case, I'd probably just flatten the stock.json file before paginating. Here's a quick prototype using the ---
# search.njk
# see search.11tydata.js for front matter.
---
<h1>{{ vehicle.brand }}</h1>
<p>{{ vehicle.range }}<p> // stock.11tydata.js
module.exports = {
pagination: {
data: "stock",
size: 1,
alias: "vehicle",
before(data) {
return data.reduce((vehicles, vehicle) => {
for (const stock of vehicle.stock) {
vehicles.push({ brand: vehicle.brand, ...stock });
}
return vehicles;
}, []);
}
},
permalink(data) {
let { brand, range, model } = data.vehicle;
brand = this.slugify(brand);
range = this.slugify(range);
model = this.slugify(model);
return `/search/${ brand }/${ range }/${ model }/`;
}
}; Note: I also had to tweak your vehicles.json file since I noticed it was mixing cases for {
"Range": "e-tron",
"Model": "300kw 55 Quattro Technik",
"Derivative": "300kW 55 Quattro 95kWh Technik 5dr Auto"
}
{
"range": "1 Series",
"model": "M140i Shadow Edition",
"derivative": "M140i Shadow Edition 5dr Step Auto",
}, |
Beta Was this translation helpful? Give feedback.
-
That's what I'd try... here's some very-barely tested code which might get you closer: // range.11tydata.njk
module.exports = {
pagination: {
data: "stock",
size: 1,
alias: "vehicle",
before(data) {
let tmp = data.reduce((vehicles, vehicle) => {
for (const stock of vehicle.stock) {
const key = `${vehicle.brand}/${stock.range}`.toLowerCase();
if (key in vehicles) {
vehicles[key].vehicles.push(stock);
} else {
vehicles[key] = {
key,
brand: vehicle.brand,
range: stock.range,
vehicles: [{ brand: vehicle.brand, ...stock }],
};
}
}
return vehicles;
}, {});
return Object.values(tmp);
},
},
eleventyComputed: {
permalink(data) {
let { brand, range } = data.vehicle;
brand = this.slugify(brand);
range = this.slugify(range);
return `/web/search/used/${brand}/${range}/`;
},
},
}; Where the modified result now returns an object/shape like this (note the one result for "audi/tt" with two vehicles in the array): [
{
key: 'audi/tt',
brand: 'Audi',
range: 'TT',
vehicles: [ [Object], [Object] ]
},
{
key: 'audi/e-tron',
brand: 'Audi',
range: 'e-tron',
vehicles: [ [Object] ]
},
{
key: 'audi/a3',
brand: 'Audi',
range: 'A3',
vehicles: [ [Object] ]
},
{
key: 'bmw/1 series',
brand: 'BMW',
range: '1 Series',
vehicles: [ [Object] ]
}
] And my sample "range.njk" looks like this: ---
# see range.11tydata.js
---
<h1>{{ vehicle.brand }} <small>{{ vehicle.range }}</small></h1>
<ul>
{% for v in vehicle.vehicles %}
<li>{{ v.model }}: {{ v.derivative }}{% if v.price %} ({{ v.price }}){% endif %}</li>
{% endfor %}
</ul>
<pre>{{ vehicle.vehicles | dump(2) | safe }}</pre> OUTPUT[11ty] Writing www/web/search/used/audi/tt/index.html from ./src/range.njk
[11ty] Writing www/web/search/used/audi/e-tron/index.html from ./src/range.njk
[11ty] Writing www/web/search/used/audi/a3/index.html from ./src/range.njk
[11ty] Writing www/web/search/used/bmw/1-series/index.html from ./src/range.njk
[11ty] Wrote 4 files in 0.05 seconds (v2.0.1) And generated this HTML masterpiece: <!-- www/web/search/used/audi/tt/index.html -->
<h1>Audi <small>TT</small></h1>
<ul>
<li>40 TFSI Sport: 40 TFSI Sport 2dr S Tronic (27,950)</li>
<li>2.0T FSI Quattro TTS Black Edition: 2.0T FSI Quattro TTS Black Edition 2dr S Tronic (29,990)</li>
</ul>
<pre>[
{
"brand": "Audi",
"range": "TT",
"model": "40 TFSI Sport",
"derivative": "40 TFSI Sport 2dr S Tronic",
"price": "27,950"
},
{
"range": "TT",
"model": "2.0T FSI Quattro TTS Black Edition",
"derivative": "2.0T FSI Quattro TTS Black Edition 2dr S Tronic",
"price": "29,990"
}
]</pre> Possibly better ways to do the same thing, this was just one of the first things that came to mind. |
Beta Was this translation helpful? Give feedback.
I think if you search the issues for "pagination" there should be a few threads for double-pagination or multi-pagination which might have some ideas. I did find #332
In your case, I'd probably just flatten the stock.json file before paginating. Here's a quick prototype using the
before()
callback: