Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to list multi level Sub-categories under their Categories if all the catgories are in the same array of objects?

I’m working on dropdown menu of categories with sub-categories, and some sub-categories has sub-categories too.
i have array of categories with parent_id property which comes from server and i want to create another array with my custom structure in client side.
parent_id : null is for main category.

Categories array coming from server

const categories = [
  { id: "10001", name: "name1", parent_id: null },
  { id: "10002", name: "name2", parent_id: "10001" },
  { id: "10003", name: "name3", parent_id: "10001" },
  { id: "10004", name: "name4", parent_id: null },
  { id: "10005", name: "name5", parent_id: null },
  { id: "10006", name: "name6", parent_id: "10002" },
  { id: "10007", name: "name7", parent_id: "10002" },
  { id: "10008", name: "name8", parent_id: "10003" },
  { id: "10009", name: "name9", parent_id: "10004" },
]

My expecting result

const categories= [
  {
    id: "10001",
    name: "name1",
    subCategories: [
      {
        id: "10002",
        name: "name2",
        subCategories: [
          { id: "10006", name: "name6" },
          { id: "10007", name: "name7" },
        ],
      },
      {
        id: "10003",
        name: "name3",
        subcategories: [{ id: "10008", name: "name8", parent_id: "10003" }],
      },
    ],
  },
  {
    id: "10004",
    name: "name4",
    subCategories: [{ id: "10009", name: "name9", parent_id: "10004" }],
  },
  { id: "10005", name: "name5" , subCategories: [] },
]

My code

this code gives the lvl-1 and lvl-2 categories but we want all sub categories in any lvl.

const result = categories
  .map((category, index, array) => {
    if (category.parent_id === null) {
      return {
        ...category,
        subCategory: array.filter((cat) => cat.parent_id === category.id),
      }
    }
    return null; // insert null in array
  })
  .filter((category) => category); // filter null items from array

// output


[
  {
    "id": "10001",
    "name": "name1",
    "parent_id": null,
    "subCategory": [
      {
        "id": "10002",
        "name": "name1",
        "parent_id": "10001"
      },
      {
        "id": "10003",
        "name": "name1",
        "parent_id": "10001"
      }
    ]
  },
  {
    "id": "10004",
    "name": "name1",
    "parent_id": null,
    "subCategory": [
      {
        "id": "10009",
        "name": "name1",
        "parent_id": "10004"
      }
    ]
  },
  {
    "id": "10005",
    "name": "name1",
    "parent_id": null,
    "subCategory": []
  }
]

as you see these categories { id: "10006"},{ id: "10007"},{ id: "10008"} are not here.
In this example we have only 3 lvl of sub-categories but it’s possible to have even more lvl of sub-categories.
Thank you .

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You can loop over all categories that have a parent_id, and assign them to their parent.
Then, in the original array, filter out all categories that have a parent.

let categories = [
  { id: "10001", name: "name1", parent_id: null },
  { id: "10002", name: "name2", parent_id: "10001" },
  { id: "10003", name: "name3", parent_id: "10001" },
  { id: "10004", name: "name4", parent_id: null },
  { id: "10005", name: "name5", parent_id: null },
  { id: "10006", name: "name6", parent_id: "10002" },
  { id: "10007", name: "name7", parent_id: "10002" },
  { id: "10008", name: "name8", parent_id: "10003" },
  { id: "10009", name: "name9", parent_id: "10004" },
];

categories
  .filter(c => c.parent_id) // For all categories that have a parent, 
  .forEach(c => {          // Assign them to that parent.
    const parent = categories.find(p => p.id === c.parent_id);
    parent.subCategories = parent.subCategories || [];
    parent.subCategories.push(c);
  });

// Now only give me categories that have no parent.
categories = categories.filter(c => !c.parent_id);
console.log(categories);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading