5

I'm building a node tree in React.js using { List, ListItem, MakeSelectable} from 'material-ui/List'. I will eventually wire up JSON data coming from an internal web service call. I have no problem declaratively creating a nested list:

<List>
...
<ListItem
    ...
    nestedItems={[
      <ListItem
        ...

What I want to do is programmatically create this nested structure from the JSON data. It's easy enough to instantiate individual <ListItem> components and .push them into an array to render, but I'm having trouble getting the nested items into the node structure on the fly.

The best I've been able to do so far is to work from the bottom up, finding a bottom level of JSON nodes, pushing them into an array, creating the parent component, assigning my previously-created array as children of the parent, etc. e.g.

var Children = [
   <ListItem key={1} primaryText='Child 1' />
   <ListItem key={2} primaryText='Child 2' />
]

then...

var Parents = [
   <ListItem key={0} primaryText='Parent 1' nestedItems={Children} />
]

This is a bit cumbersome; is there a more graceful way to map up parents with nested children into a material-ui <List>?

2 Answers 2

7

Imagine that we have an object similar to the following...

RootObject = {
  children: [
    {
      children: [
        {
          children: [ {...props}, {...props}]
        },
        ...props,
      ]
    },
    {
      children: [...],
    },
    ...
    {
      children: [],
    },
  ],
  ...props,
}

Now we need to create a tree node that will call itself recursively:

const mapStructure = (nodes) => {
  if (nodes) {
    return nodes.map(node => (
      <ListItem
        key={node.id}
        primaryText={node.primaryText}
        initiallyOpen //optional
        nestedItems={mapStructure(node.children)}
      />
    ));
  }
};

And finally:

const DynamicNestedItems = ({ RootObject }) => {
  return (
    <List>
      {mapStructure(RootObject)}
    </List>
  );
};

export default DynamicNestedItems;
Sign up to request clarification or add additional context in comments.

Comments

1

I had the very same problem, the only difference is that I have a menu hierarchy described in XML instead of JSON.

I created a main component ConfigurationNav that you can instantiate with <ConfigurationNav nav={this.state.nav}/>:

var ConfigurationNav = React.createClass({
  render: function() {
    var items = [];
    var _this = this;
    this.props.nav.find('> navitem').each(function(i) {
      items.push(<ConfigurationNavItem item={this} />);
    });

    return (
      <List>
        {items}
      </List>
    );
  }
});

Then there is a subcomponent that creates the ListItems:

var ConfigurationNavItem = React.createClass({
  render: function() {
    var nested = [];
    for (var i=0; i<this.props.item.children.length; i++) {
      nested.push(<ConfigurationNavItem item={this.props.item.children[i]} />);
    }

    return (
      <ListItem key={this.props.item.id}
          primaryText={this.props.item.getAttribute('label')}
          nestedItems={nested}
          />
    );
  }
});

This approach works for me, but somehow I lost the indent of the nested items, still working on it.

Luca

Comments

Your Answer

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.