[RESOLVED] Can't get the data from nested components within dynamic zones

System Information
  • Strapi Version: 4.1.0
  • Operating System: macOS Monterey
  • Database: sqllite
  • Node Version: 14.17.3
  • NPM Version: 6.14.13
  • Yarn Version: 1.22.10

Consider a collection type, Page, which has two fields, a title of type text and sessions of type dynamic zone.

To simplify, let’s consider that the dynamic zone only accepts one type of component, carrousel.

The carrousel component has two fields, title of type text and items of type Component (repeatable). The component within items is the carrouselItem which has two fields description and image.

I’ve then added data:

After that I tried to query the data with http://localhost:1337/api/pages?populate=* but I did not get all the nested data within the dynamic zone:

{
    "data": [
        {
            "id": 1,
            "attributes": {
                "title": "test",
                "createdAt": "2022-02-20T05:39:14.275Z",
                "updatedAt": "2022-02-20T05:47:17.626Z",
                "publishedAt": "2022-02-20T05:47:17.625Z",
                "sessions": [
                    {
                        "id": 1,
                        "__component": "session.carrousel",
                        "title": "test"
                    }
                ]
            }
        }
    ],
    "meta": {
        "pagination": {
            "page": 1,
            "pageSize": 25,
            "pageCount": 1,
            "total": 1
        }
    }
}

I did some research and found this suggestion, https://forum.strapi.io/t/strapi-v4-populate-media-and-dynamiczones-from-components/12670/3. I went ahead and added the helper to my code base and modified the home controller.

Unfortunately, that didn’t change my query result and I’m still not getting the expected nested content.

note: I’ve also tried to fetch the data with http://localhost:1337/api/pages?populate[sessions][populate][carrousel][populate][carrouselItem][populate]=* but got the same result.

Please advise.

[RESOLVED] :slight_smile:

I managed to get the data after modifying the populate help thanks to this suggestion https://forum.strapi.io/t/strapi-v4-populate-media-and-dynamiczones-from-components/12670/15.

const { createCoreController } = require("@strapi/strapi/lib/factories");

const populateAttribute = ({ components }) => {
  if (components) {
    const populate = components.reduce((currentValue, current) => {
      const [componentDir, componentName] = current.split('.');

      /* Component attributes needs to be explicitly populated */
      const componentAttributes = Object.entries(
        require(`../components/${componentDir}/${componentName}.json`).attributes,
      ).filter(([, v]) => v.type === 'component');

      const attrPopulates = componentAttributes.reduce(
        (acc, [curr]) => ({ ...acc, [curr]: { populate: '*' } }),
        {},
      );

      return { ...currentValue, [current.split('.').pop()]: { populate: '*' }, ...attrPopulates };
    }, {});
    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, () => {    
    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;
1 Like

The same situation, but for GraphQL…
Is there any elastic way to request dynamic zones via Graphql without explicitly defining each of them in a query?
For example, I DON’T want to do something like this:

query Homepage {
  components {
    ... on SliderComponent {
      image
      text
    }
    ... on ParagraphComponent {
      title
      description
    }
    // and so on...
  }
}

Instead, somehow, I’d like to be able to get all of the dynamic zones without querying them separately.
So ideally would be something like this:

query Homepage {
  components
}

and that would return all of the possible dynamic zone components with their nested fields.

The best scenario is to query all the nested data within the dynamic zones using something like in RestApi http://localhost:1337/api/pages?populate[dynamiczones]

NOTE: I know that the queries above are not correct, but this is just an idea of the query shape.

Try this

2 Likes

Hi chris_p, did you ever figure out how to do it? I have the exact same problem, and I am looking a simplify query in GraphQL.

query truthLendingDisclosures {
  truthLendingDisclosures {
    data {
      id
      attributes {
        title
        body {
          __typename
          ... on ComponentPagesDynamicSection {
            section {
              id
              title
              text
              value
              __typename
            }
          }
          ... on ComponentPagesStaticSection {
            section {
              id
              title
              text
              __typename
            }
          }
        }
      }
    }
  }
}

I want to be able to iterate through my results and replace anything in the field “value” with an external data.

{
    "data": {
        "truthLendingDisclosures": {
            "data": [
                {
                    "id": "1",
                    "attributes": {
                        "title": "Truth in Lending Disclosure",
                        "body": [
                            {
                                "__typename": "ComponentPagesDynamicSection",
                                "section": [
                                    {
                                        "id": "1",
                                        "title": null,
                                        "text": "Account #",
                                        "value": "{1-123456-1}",
                                        "__typename": "ComponentSharedDynamicContent"
                                    },
                                    {
                                        "id": "2",
                                        "title": null,
                                        "text": "Finance Charge Start Date",
                                        "value": "{07/21/2022}",
                                        "__typename": "ComponentSharedDynamicContent"
                                    },
                                    {
                                        "id": "3",
                                        "title": null,
                                        "text": "Amount of Pays [X] through [Y]",
                                        "value": "{$###.##}",
                                        "__typename": "ComponentSharedDynamicContent"
                                    },
                                    {
                                        "id": "4",
                                        "title": null,
                                        "text": "Amount of Payments [Z]",
                                        "value": "$###.##",
                                        "__typename": "ComponentSharedDynamicContent"
                                    },
                                    {
                                        "id": "5",
                                        "title": null,
                                        "text": "Due [Frequency] Starting",
                                        "value": "{07/21/2022}",
                                        "__typename": "ComponentSharedDynamicContent"
                                    },
                                    {
                                        "id": "6",
                                        "title": "Annual Percentage Rate",
                                        "text": "The cost of your credit as a yearly rate.",
                                        "value": "{###.##% APR}",
                                        "__typename": "ComponentSharedDynamicContent"
                                    },
                                    {
                                        "id": "7",
                                        "title": "Finance Charge",
                                        "text": "The dollar amount the credit cost you.",
                                        "value": "{$#,###.##}",
                                        "__typename": "ComponentSharedDynamicContent"
                                    },
                                    {
                                        "id": "8",
                                        "title": "Amount Financed",
                                        "text": "The amount of credit provided to you on your behalf.",
                                        "value": "{$#,###.##}",
                                        "__typename": "ComponentSharedDynamicContent"
                                    },
                                    {
                                        "id": "9",
                                        "title": "Total of Payments",
                                        "text": "The amount you will have paid after you have made all payments as scheduled.",
                                        "value": "{$#,###.##}",
                                        "__typename": "ComponentSharedDynamicContent"
                                    },
                                    {
                                        "id": "10",
                                        "title": "Total Sale Price",
                                        "text": "The total cost of your purchase on credit, including your down payment of [$###.##].",
                                        "value": "{$#,###.##}",
                                        "__typename": "ComponentSharedDynamicContent"
                                    }
                                ]
                            },
                            {
                                "__typename": "ComponentPagesStaticSection",
                                "section": [
                                    {
                                        "id": "1",
                                        "title": "Security Interest",
                                        "text": "You are giving a security interest in the Goods you are purchasing, the below Electronic Missed Payment Authorization, RCP Authorization, and Payment Authorization (if applicable). The Electronic Missed Payment Authorization, RCP Authorization, and Payment Authorization (if applicable) securing other agreements with us may also secure this Agreement.",
                                        "__typename": "ComponentSharedStaticContent"
                                    },
                                    {
                                        "id": "2",
                                        "title": "Late Charge",
                                        "text": "[If you fail to pay any payment in full within # days after it is due, you may be charged a late fee equal to #% of the payment due or $##, whichever is more.]",
                                        "__typename": "ComponentSharedStaticContent"
                                    },
                                    {
                                        "id": "3",
                                        "title": "Prepayment",
                                        "text": "See the Loan Agreement below for information about nonpayment, default, any required repayment in full before the scheduled date, and prepayment refunds and penalties. ",
                                        "__typename": "ComponentSharedStaticContent"
                                    }
                                ]
                            }
                        ]
                    }
                }
            ]
        }
    }
}

it good for me. Thanks