We had the same problem with deeply nested components in dynamiczones. After a bit of fiddling, this is what we came up with.
Created a new file src/helpers/populate.js
const { createCoreController } = require("@strapi/strapi/lib/factories");
function populateAttribute({ components }) {
if (components) {
const populate = components.reduce((currentValue, current) => {
return { ...currentValue, [current.split(".").pop()]: { populate: "*" } };
}, {});
return { populate };
}
return { populate: "*" };
}
const getPopulateFromSchema = function (schema) {
return Object.keys(schema.attributes).reduce((currentValue, current) => {
const attribute = schema.attributes[current];
if (!["dynamiczone", "component"].includes(attribute.type)) {
return currentValue;
}
return {
...currentValue,
[current]: populateAttribute(attribute),
};
}, {});
};
function createPopulatedController(uid, schema) {
return createCoreController(uid, () => {
console.log(schema.collectionName, getPopulateFromSchema(schema));
return {
async find(ctx) {
ctx.query = {
...ctx.query,
populate: getPopulateFromSchema(schema),
};
return await super.find(ctx);
},
async findOne(ctx) {
ctx.query = {
...ctx.query,
populate: getPopulateFromSchema(schema),
};
return await super.findOne(ctx);
},
};
});
}
module.exports = createPopulatedController;
then in controllers needing to be deeply populated:
"use strict";
/**
* homepage controller
*/
const schema = require("../content-types/homepage/schema.json");
const createPopulatedController = require("../../../helpers/populate");
module.exports = createPopulatedController("api::homepage.homepage", schema);
What it basically does, is overriding the default controller by dynamically creating a “populate” query from the content type schema. I hope it might help someone…