Barelydead / strapi-plugin-populate-deep

A Strapi plugin that makes it easier to populate deep content structures
172 stars 39 forks source link

Some images are not populated in a dynamic zone when repeatable field named as "items" #42

Open whitetown opened 11 months ago

whitetown commented 11 months ago

I discovered some weird bug with naming.

I have a collection "pages". it contains a dynamic zone (sections) with a few components. For example there are four components:

All these components have another, the same repeatable component.

For some reason images are not populated in cards and instructions

you can see see the output from the api there: https://cms.propera.ch/api/energy-pages/43?populate=deep,10

if I explicitly ask to populate sections.items.image - it returns the image for cards and instructions https://cms.propera.ch/api/energy-pages/43?populate[0]=sections.items.image but of course everything else is missing

What could be a reason? Initially I blamed myself, then recently updated strapi, so I tried to downgrade it. Finally I added one more repeatable field to "cards" and named it differently (cards:). and images start working for the field.

initial compare hero and cards

hero-cards

the same component in tabs

tabs

the same component in cards but named differently

cards

So I think that it's definitely because of the name "items".

of course I can rename it although it requires some extra work for me on the company web portal. :/

HonzaTuron commented 11 months ago

Hey @whitetown, we had similar issues with fields not being populated in some dynamic zones. Following patch fixed it (used with patch-package library)

diff --git a/node_modules/strapi-plugin-populate-deep/server/helpers/index.js b/node_modules/strapi-plugin-populate-deep/server/helpers/index.js
index 7f026b8..e82c1ee 100644
--- a/node_modules/strapi-plugin-populate-deep/server/helpers/index.js
+++ b/node_modules/strapi-plugin-populate-deep/server/helpers/index.js
@@ -1,4 +1,20 @@
-const { isEmpty, merge } = require("lodash/fp");
+const { isEmpty } = require("lodash/fp");
+
+const deepAssign = (target, source) => {
+    for (const key in source) {
+      if (Object.prototype.hasOwnProperty.call(source, key)) {
+        if (typeof source[key] === 'object' && source[key] !== null) {
+          if (!target[key] || typeof target[key] !== 'object' || target[key] === null) {
+            target[key] = source[key];
+          }
+          deepAssign(target[key], source[key]);
+        } else if (!target[key] || typeof target[key] !== 'object' || target[key] === null) {
+          target[key] = source[key];
+        }
+      }
+    }
+    return target;
+}

 const getModelPopulationAttributes = (model) => {
   if (model.uid === "plugin::upload.file") {
@@ -32,7 +48,7 @@ const getFullPopulateObject = (modelUid, maxDepth = 20, ignore) => {
       } else if (value.type === "dynamiczone") {
         const dynamicPopulate = value.components.reduce((prev, cur) => {
           const curPopulate = getFullPopulateObject(cur, maxDepth - 1);
-          return curPopulate === true ? prev : merge(prev, curPopulate);
+          return curPopulate === true ? prev : deepAssign(prev, curPopulate);
         }, {});
         populate[key] = isEmpty(dynamicPopulate) ? true : dynamicPopulate;
       } else if (value.type === "relation") {
whitetown commented 11 months ago

Hey @whitetown, we had similar issues with fields not beint populated in some dynamic zones. Following patch fixed it (used with patch-package library)

Wow. it helped. thanks a lot!

y-nk commented 9 months ago

same here, but my collections are not named items but rather links - that said the image inside is named image.

JunkyDeLuxe commented 7 months ago

Hey, encounter the same problem ... When the fix will be delivered as a new release plz ?

denglert23 commented 2 months ago

without changing the code in the suggestion I was able to see this working by changing:

http://localhost:1337/api/homepage?populate=deep to http://localhost:1337/api/homepage?populate=deep,10

this made the images in my dynamic / repeating component render in the JSON.

maybe this had already been fixed in the plugin and/or strapi? i just installed yesterday:

"dependencies": { "@strapi/plugin-cloud": "4.24.5", "@strapi/plugin-graphql": "^4.24.5", "@strapi/plugin-i18n": "4.24.5", "@strapi/plugin-users-permissions": "4.24.5", "@strapi/strapi": "4.24.5", "better-sqlite3": "8.6.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-router-dom": "5.3.4", "strapi-plugin-populate-deep": "^3.0.1", "styled-components": "5.3.3" },

vuletiki commented 1 month ago

Hey @whitetown, we had similar issues with fields not being populated in some dynamic zones. Following patch fixed it (used with patch-package library)

diff --git a/node_modules/strapi-plugin-populate-deep/server/helpers/index.js b/node_modules/strapi-plugin-populate-deep/server/helpers/index.js
index 7f026b8..e82c1ee 100644
--- a/node_modules/strapi-plugin-populate-deep/server/helpers/index.js
+++ b/node_modules/strapi-plugin-populate-deep/server/helpers/index.js
@@ -1,4 +1,20 @@
-const { isEmpty, merge } = require("lodash/fp");
+const { isEmpty } = require("lodash/fp");
+
+const deepAssign = (target, source) => {
+    for (const key in source) {
+      if (Object.prototype.hasOwnProperty.call(source, key)) {
+        if (typeof source[key] === 'object' && source[key] !== null) {
+          if (!target[key] || typeof target[key] !== 'object' || target[key] === null) {
+            target[key] = source[key];
+          }
+          deepAssign(target[key], source[key]);
+        } else if (!target[key] || typeof target[key] !== 'object' || target[key] === null) {
+          target[key] = source[key];
+        }
+      }
+    }
+    return target;
+}

 const getModelPopulationAttributes = (model) => {
   if (model.uid === "plugin::upload.file") {
@@ -32,7 +48,7 @@ const getFullPopulateObject = (modelUid, maxDepth = 20, ignore) => {
       } else if (value.type === "dynamiczone") {
         const dynamicPopulate = value.components.reduce((prev, cur) => {
           const curPopulate = getFullPopulateObject(cur, maxDepth - 1);
-          return curPopulate === true ? prev : merge(prev, curPopulate);
+          return curPopulate === true ? prev : deepAssign(prev, curPopulate);
         }, {});
         populate[key] = isEmpty(dynamicPopulate) ? true : dynamicPopulate;
       } else if (value.type === "relation") {

I was looking for morph logic in strapi source for whole day and saw your comment. You saved me sirrrrr!!