4

I created menus component. In menus component one more component is there which is submenu component so its one nested component is made. But I want to import this menus component in another component which is one header component but in strapi headless cms showing the error. Strapi allowing only one nested component. they are not allowing one nested component import in to another nested component. how should I do? please if any solution is there share it.

3 Answers3

1

The issue here is the fact that Strapi only allows a depth level of 2 by default. This is a feature, rather than a bug, to ensure your app runs and loads smoothly, without having to render through multiple depth levels.

More information is also available on this discussion forum: Strapi Depth Level Discussion

However, as a work around, you can use a patch to allow higher depth levels to nest multiple components on each other.

These are your steps:

  1. Install patch-package yarn add patch-package or npm i patch-package --save
  2. Add script to your package.json "postinstall": "patch-package". This will allow the patch-package command to run after every npm install you do.
  3. Create file patches/@strapi+plugin-content-manager+4.0.4.patch
  4. Paste Code:
diff --git a/node_modules/@strapi/plugin-content-manager/server/services/entity-manager.js b/node_modules/@strapi/plugin-content-manager/server/services/entity-manager.js
index df4b28e..c0910f0 100644
--- a/node_modules/@strapi/plugin-content-manager/server/services/entity-manager.js
+++ b/node_modules/@strapi/plugin-content-manager/server/services/entity-manager.js
@@ -1,6 +1,7 @@
 'use strict';
 
 const { assoc, has, prop, omit } = require('lodash/fp');
+const merge = require('lodash/merge');
 const strapiUtils = require('@strapi/utils');
 const { ApplicationError } = require('@strapi/utils').errors;
 
@@ -39,13 +40,15 @@ const findCreatorRoles = entity => {
   return [];
 };
 
+const deepMerge = (oldData, newData) => oldData ? merge(oldData, newData) : newData;
+
 // TODO: define when we use this one vs basic populate
 const getDeepPopulate = (uid, populate, depth = 0) => {
   if (populate) {
     return populate;
   }
 
-  if (depth > 2) {
+  if (depth > 4) {
     return {};
   }
 
@@ -73,7 +76,7 @@ const getDeepPopulate = (uid, populate, depth = 0) => {
     if (attribute.type === 'dynamiczone') {
       populateAcc[attributeName] = {
         populate: (attribute.components || []).reduce((acc, componentUID) => {
-          return Object.assign(acc, getDeepPopulate(componentUID, null, depth + 1));
+          return deepMerge(acc, getDeepPopulate(componentUID, null, depth + 1));
         }, {}),
       };
     }
  1. Add file patches/@strapi+plugin-content-type-builder+4.0.4.patch
  2. Paste code
diff --git a/node_modules/@strapi/plugin-content-type-builder/admin/src/components/SelectComponent/index.js b/node_modules/@strapi/plugin-content-type-builder/admin/src/components/SelectComponent/index.js
index 0c692d8..5d96d05 100644
--- a/node_modules/@strapi/plugin-content-type-builder/admin/src/components/SelectComponent/index.js
+++ b/node_modules/@strapi/plugin-content-type-builder/admin/src/components/SelectComponent/index.js
@@ -47,11 +47,11 @@ const SelectComponent = ({
     return [...acc, ...compos];
   }, []);
 
-  if (isAddingAComponentToAnotherComponent) {
-    options = options.filter(option => {
-      return !componentsThatHaveOtherComponentInTheirAttributes.includes(option.uid);
-    });
-  }
+  // if (isAddingAComponentToAnotherComponent) {
+  //   options = options.filter(option => {
+  //     return !componentsThatHaveOtherComponentInTheirAttributes.includes(option.uid);
+  //   });
+  // }
 
   if (isTargetAComponent) {
     options = options.filter(option => {
diff --git a/node_modules/@strapi/plugin-content-type-builder/server/controllers/validation/types.js b/node_modules/@strapi/plugin-content-type-builder/server/controllers/validation/types.js
index 735f4ea..faab13f 100644
--- a/node_modules/@strapi/plugin-content-type-builder/server/controllers/validation/types.js
+++ b/node_modules/@strapi/plugin-content-type-builder/server/controllers/validation/types.js
@@ -237,12 +237,12 @@ const getTypeShape = (attribute, { modelType, attributes } = {}) => {
               const targetCompo = strapi.components[compoUID];
               if (!targetCompo) return true; // ignore this error as it will fail beforehand
 
-              if (modelType === modelTypes.COMPONENT && hasComponent(targetCompo)) {
-                return this.createError({
-                  path: this.path,
-                  message: `${targetCompo.modelName} already is a nested component. You cannot have more than one level of nesting inside your components.`,
-                });
-              }
+              // if (modelType === modelTypes.COMPONENT && hasComponent(targetCompo)) {
+              //   return this.createError({
+              //     path: this.path,
+              //     message: `${targetCompo.modelName} already is a nested component. You cannot have more than one level of nesting inside your components.`,
+              //   });
+              // }
               return true;
             },
           })
  1. Run install yarn install or npm install
  2. Remove .cache and build folders
  3. Build admin yarn build or npm run build

Found this solutions thanks to lukasz-mical in GitHub under Strapi Issues. Worked wonders in my application to. Hope it works for you too :)

nuvin.ga
  • 21
  • 1
  • 4
0

There is a long thread about it on strapi.forum.io

They mention that this limit is now removed in this Github PR

Jean Claveau
  • 1,101
  • 1
  • 13
  • 15
0

Its not possible from the UI as it still has the restriction to 2 level nesting. However you can directly do it in schema files. Here is an example what I have in my project.

enter image description here

The schema files for this are as below main component

{
  "collectionName": "components_product_upload_boxes",
  "info": {
    "displayName": "productUploadBox",
    "icon": "chevron-circle-up"
  },
  "options": {},
  "attributes": {
    "title": {
      "type": "string",
      "column": {
        "type": "text"
      }
    },
    "boxTitle": {
      "type": "string",
      "column": {
        "type": "text"
      }
    },
    "productUploadSteps": {
      "type": "component",
      "repeatable": true,
      "component": "components.upload-section"
    }
  }
}

upload-section.json mentioned in the main schema file

{
  "collectionName": "components_upload_sections",
  "info": {
    "displayName": "uploadSection",
    "icon": "cash-register"
  },
  "options": {},
  "attributes": {
    "title": {
      "type": "string",
      "column": {
        "type": "text"
      },
      "required": true
    },
    "textContent": {
      "type": "richtext"
    },
    "imageStepsBox": {
      "type": "component",
      "repeatable": true,
      "component": "components.image-steps-box"
    }
  }
}

image-steps-box file schema

{
  "collectionName": "components_image_steps_boxes",
  "info": {
    "displayName": "imageStepsBox",
    "icon": "chart-area"
  },
  "options": {},
  "attributes": {
    "steps": {
      "type": "component",
      "repeatable": true,
      "component": "components.step-content"
    },
    "image": {
      "type": "media",
      "allowedTypes": ["images", "files", "videos"],
      "multiple": false,
      "required": false
    }
  }
}

Similarly I have for further component of step-content as well.

The main catch over here is you need to add the component manually in the component schema file and then you can add n number of child components.