How to make multi-level (nested) categories in Strapi v3?
How do I correctly build a nested list of categories so I could use it in frontend with <select>
box element ?
Collection Type "Categories" have following fields:
- categories.id
- categories.name
- categories.category
the handler is in /api/categories/controllers/categories.js
:
async nested(ctx) {
let entities = await strapi.services.categories.find(ctx.query);
const cleaned = entities.map(entity => {
const item = sanitizeEntity(entity, { model: strapi.models.categories });
return item;
})
return nestChilds(cleaned);
}
function nestChilds (object) {
const list = [];
object.forEach(i => {
console.log('LIST:', list);
if (!i.parent) {
list.push(i);
} else {
const parent = list.find(x => x.id === i.parent.id);
parent.childs = [];
parent.childs.push(i);
}
})
return list;
}
But it's not working. I would like to have some sort of these results:
[
{
id: 1,
name: "Top-level category",
childs: [
{
id: 2,
name: "2nd level category 1"
},
{
id: 3,
name: "2nd level category 2",
childs: [
{
id: 5,
name: "3rd level category 1"
}
]
},
{
id: 4,
name: "2nd level category 3"
}
]
}
]
Is there any solution or maybe someone could kickstart me with an idea ?
Solution 1:
So I came up with the following solution:
function nestChilds (object) {
const list = [];
object.forEach(i => {
// If is related to parent
if (i.parent) {
// Scope that parent
const parent = object.find(({ id }) => id === i.parent.id);
// Add a child array property to that parent if not already done
if (!parent.hasOwnProperty('childs')) parent.childs = [];
// Add current item to it's corresponding parent
parent.childs.push(i);
// Remove parent property
delete i.parent;
} else {
list.push(i);
}
})
return list;
}