skip to Main Content

Let’s say I have a nested JSON object variable like:

{
  "A":{
    "a": [1,2],
    "b": [3]
  },
  "B":{
    "c":[4],
  }
}

And I want it to be displayed in relative-sized tabular form like:

example

I have considered several methods and I found that every each method has some trick points to display in even table format.

Since each side of the cells must have the same length as its adjacent cell in both row and column directions, using div tag must be very tricky without absolute size. Even without that table head part, I think it won’t be easy to match each side between "A" part and "B" part in the example picture.

So, I guess using table tag might be the best choice. But using table will require destructuring all objects and complicated illegible additional code for calculating each row span, which is super non-declarative and degrades the readability significantly.

Is there any better alternative way to display nested object in tabular format with relative sizes in React, HTML?

2

Answers


  1. I think it’s best you have used

    const nestedObject = {
    A: {
      a: [1, 2],
      b: [3],
    },
    B: {
      c: [4],
    },
    

    };

    Login or Signup to reply.
  2. Below is my attempt at this problem with recursion to fill the cell rowSpan at each level

    import React from "react";
    
    // Rearranged consistent data format
    const data = [
      {
        label: "A",
        children: [
          { label: "a", children: [{ label: "1" }, { label: "2" }] },
          { label: "b", children: [{ label: "3" }] },
        ],
      },
      {
        label: "B",
        children: [{ label: "c", children: [{ label: "4" }] }],
      },
    ];
    
    // Traverse each level recursively to find the rowSpan for each cell and rearranging to column data
    const traverse = (nodes, results, depth = 0) => {
      let counter = 0;
      if (!results[depth]) results[depth] = [];
      const result = results[depth];
      for (let node of nodes) {
        // Each cell rowSpan will be the sum of all children's rowSpan
        node.height = node.children
          ? traverse(node.children, results, depth + 1)
          : 1;
        counter += node.height;
        result.push(node);
    
        // Pushing null to cover rowSpan space
        for (var i = 0; i < node.height - 1; i++) {
          result.push(null);
        }
      }
      return counter;
    };
    
    const results = [];
    traverse(data, results);
    
    const Table = () => {
      // Results is arranged based on column, but the rendering is per row
      // We have to invert the 2d index
      let content = [];
      for (let i = 0; i < results[0].length; i++) {
        let innerContent = [];
        for (let j = 0; j < results.length; j++) {
          let cell = results[j][i];
          innerContent.push(
            !cell ? null : (
              <th key={j} rowSpan={cell.height}>
                {cell.label}
              </th>
            )
          );
        }
    
        content.push(<tr key={i}>{innerContent}</tr>);
      }
    
      return <table>{content}</table>;
    };
    
    export default Table;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search