Skip to main content
  1. About
  2. For Teams
Asked
Viewed 13k times
3

I am making a treeview from JSON using react. So far I have made a collapsible tree using this example data:

var data = {
      title: "Node 1",
      childNodes: [
        {title: "Childnode 1.1"},
        {title: "Childnode 1.2",
          childNodes: [
            {title: "Childnode 1.2.1",
              childNodes: [
                {title: "Childnode 1.2.1.1"}
              ]}, {title: "Childnode 1.2.2"}
          ]}
      ]
    };

But this is one object. I want to get JSON array of objects as input and generate treeview from that but I am unable to understand where to change the code.

Here's my render function:

render() {
    var childNodes;

    if (this.props.node.childNodes != null) {
      childNodes = this.props.node.childNodes.map(function (node, index) {
        return <li key={index}><Treeview node={node}/></li>
      });
    }

    return (
      <form>
        <div>
          <input type="checkbox"/>
          <label for>{this.props.node.title}</label>
        </div>
        <ul>
          {childNodes}
        </ul>
      </form>

    );
  }

How can I change the code to work with the whole array and not just one object?

4
  • so you want the Treeview component to accept an array of objects? or you want to turn an array into an object for Treeview?
    Robbie Milejczak
    –  Robbie Milejczak
    2017-11-08 17:05:10 +00:00
    Commented Nov 8, 2017 at 17:05
  • I want to Treeview component to accept an array of objects, for example: [{"id":28,"Title":"Sweden"}, {"id":56,"Title":"USA"}, {"id":89,"Title":"England"}]
    user8907896
    –  user8907896
    2017-11-08 17:15:23 +00:00
    Commented Nov 8, 2017 at 17:15
  • Okay let me see the code for the Treeview component
    Robbie Milejczak
    –  Robbie Milejczak
    2017-11-08 17:15:51 +00:00
    Commented Nov 8, 2017 at 17:15
  • The code I posted is if Treeview component. I am rendering this code block inside Treeview i.e recursively
    user8907896
    –  user8907896
    2017-11-08 21:02:48 +00:00
    Commented Nov 8, 2017 at 21:02

3 Answers 3

9

Recursion is fun!

const data = [{
  title: "Node 1",
  childNodes: [
    { title: "Childnode 1.1" },
    {
      title: "Childnode 1.2",
      childNodes: [
        {
          title: "Childnode 1.2.1",
          childNodes: [
            { title: "Childnode 1.2.1.1" }
          ]
        }, { title: "Childnode 1.2.2" }
      ]
    }
  ]
}];

const App = () => (
  <form>
    <Tree data={data} />
  </form>
);

const Tree = ({data}) => ( 
  <ul>
    {data && data.map(item => (
      <li>
        {item.title}
        {item.childNodes && <Tree data={item.childNodes} />}
      </li>
    ))}
  </ul>
);

Demo: https://codesandbox.io/s/01kl2xmo40

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks a lot. It worked. Is it any way to separate the 'div' for parent and child nodes so the tree is collapsible when checkbox is toggled?
Sorry, I updated to use list items instead of divs. Just put an onClick handler on the ul and toggle a "visibility" state for the tree component and then conditionally render based on that. You'd have to make it a stateful class component (not the current stateless functional component).
Can you share the code related to toggle, if possible.
codesandbox.io/s/unruffled-babbage-9knrz. Here how to fix the toggle option
1

This example below can work on all json objects i have tested it on checkout my github repo: https://github.com/nickjohngray/blockout/blob/master/src/Tree/Tree.tsx the html generated is the same as https://www.w3schools.com/howto/howto_js_treeview.asp

class Tree extends React.Component {

   

    processObject = (object) =>
        Object.keys(object).map((key, reactKey) => {
            return (
                <li key={reactKey + key}>
                    {this.buildNode(key)}
                    <ul className="nested">
                        {this.isPrimative(object[key]) ? this.buildLeaf(object[key]) :
                            this.isArray(object[key]) ? this.loopArray(object[key]) : this.processObject(object[key])}
                    </ul>
                </li>
            )
        })

    loopArray = (array) =>
        array.map((value, key) =>
            <div key={key + value}>
                {this.isPrimative(value) ? this.buildLeaf(value) :
                    this.isArray(value) ? this.loopArray(value) : this.processObject(value)}
            </div>
        )

    isArray = (value) =>
        Array.isArray(value)

    isPrimative = (value) => {
        return typeof (value) === 'string'
            || typeof (value) === 'number'
            || typeof (value) === 'boolean'
    }

    buildNode = (key: string) =>
        <span className="node"
              onClick={
                  (e) => {
                      this.toggle(e)
                  }}>
             {key}
            </span>

    buildLeaf = (value: string) =>
        <li className="leaf"
            onClick={
                (e) => {

                }}>
            {value}
        </li>

    toggle = (event) => {
        event.target.parentElement.querySelector(".nested").classList.toggle("active");
        event.target.classList.toggle("node-down");
    }

    render = () => <>
        <ul id="myUL">
            {this.processObject(json)}
        </ul>
    </>
}

export default Tree;

this is the css for it, copied from wc3 schools

/* Remove default bullets */
ul, #myUL {
    list-style-type: none;
}

body {
    background: red;
}


/* Remove margins and padding from the parent ul */
#myUL {
    margin: 0;
    padding: 0;
}

/* Style the caret/arrow */
.caret {
    cursor: pointer;
    user-select: none; /* Prevent text selection */
    background: red;
}

/* Create the caret/arrow with a unicode, and style it */
.caret::before {
    content: "\25B6";
    color: black;
    display: inline-block;
    margin-right: 6px;
}

/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.caret-down::before {
    transform: rotate(90deg);
}

/* Hide the nested list */
.nested {
    display: none;
}

/* Show the nested list when the user clicks on the caret/arrow (with JavaScript) */
.active {
    display: block;
}

2 Comments

I am not able to find caret and other toggle functionality, can you guide me or create sandbox for reference. Thanks..
1

I was also searching for a similar feature. developed a fully customizable lightweight tree generator component.

You can pass custom child and parent components for a better view

helpful for users who are searching for the same.

https://www.npmjs.com/package/react-custom-tree

Comments

Your Answer

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.

Morty Proxy This is a proxified and sanitized view of the page, visit original site.