Code Monkey home page Code Monkey logo

react-tree-menu's Introduction

React Tree Menu Component

A stateless tree component with the following features:

  • Checkboxes
  • Collapsible nodes
  • Dynamic tree generation
  • Declarative tree menus
  • Built with the Flux proposal in mind (i.e. trickle-down state)

Please check out the Demo.

Install

npm install --save react-tree-menu

General Usage


var TreeMenu = require('react-tree-menu').TreeMenu,
    TreeNode = require('react-tree-menu').TreeNode;

    ...

    <TreeMenu/>
    <TreeMenu>
        <TreeNode/>
    </TreeMenu>

Exports

This package exports the following:

module.exports = {
  TreeMenu: require('./src/TreeMenu.jsx'),
  TreeNode: require('./src/TreeNode.jsx'),
  Utils: require('./src/TreeMenuUtils')
};

Declarative use

In your .render() method, embed TreeMenu:

      return <TreeMenu
        identifier={"id"}
        onTreeNodeClick={this._setLastActionState.bind(this, "clicked")}
        onTreeNodeCheckChange={this._setLastActionState.bind(this, "checked")}
        collapsible={false}
        expandIconClass="fa fa-chevron-right"
        collapseIconClass="fa fa-chevron-down">
        <TreeNode label="Option 1" id="option_1"/>
        <TreeNode label="Option 2" collapsible={false} id="option_2">
          <TreeNode label="Option A" checkbox={true} id="option_2.a"/>
          <TreeNode label="Option B" checkbox={true} id="option_2.b"/>
        </TreeNode>
        <TreeNode label="Option 3" id="option_3"/>
        <TreeNode label="Option 4" id="option_4"/>
      </TreeMenu>;

Dynamic use w/ the 'data' prop

In your .render() method, embed TreeMenu with a data prop:

var data = [{
             label : "Option 1"
           },
           {
             label : "Option 2",
             children : [
               {
                 checkbox: true,
                 label: "Sub Option A",
                 children: [
                   {
                     label: "Third Level Nest Option 1",
                     checkbox : true
                   },
                   {
                     label: "Third Level Nest Option 2",
                     checkbox : true
                   }
                 ]
               },
               {
                 checkbox: true,
                 label: "Sub Option B"
               }
             ]
           }];

      return <TreeMenu
        onTreeNodeClick={...}
        onTreeNodeCollapseChange={...}
        onTreeNodeCheckChange={...}
        data={data} />;

<TreeMenu/> Style Guide

To style <TreeMenu/>, use the following props:

See the example CSS for how this works.

<TreeMenu/> Props

sort={<Boolean> || <Function>}

  • If sort is a Boolean and true (i.e. <TreeMenu sort ... />), the node label will be used for sorting.
  • If sort is a Function, it will be used as the sort function, with the argument the React element (props are available for sorting). Example:
<TreeMenu sort={(node) => node.props.value} ... />

stateful={<Boolean>}

If you need it, you can make <TreeMenu/> keep track of its own state. That being said, react-tree-menu was designed to fit inside Flux architecture, which encourages components to render based on props passed from the Controller-View. Defaults to false.

classNamePrefix={<String>}

The prefix to put in front of all the CSS classes for nested element (like the container for the menu, the checkbox, etc)

identifier={<String>}

Optional prop/field to use for the node identifier. Defaults to Array index

collapsible={<Boolean>}

Whether or not nested components are collapsible. Defaults to true.

expandIconClass={<String>}

The CSS class to give the expand icon component. Empty by default.

collapseIconClass={<String>}

The CSS class to give the collapse icon component. Empty by default

labelFilter={<Function>}

A function that can be used to filter/transform the label. Empty by default

labelFactory={<Function>}

A factory function that returns a label node. See example source for usage.

checkboxFactory={<Function>}

A factory function that returns a checkbox node. See example source for usage.

onTreeNodeClick={<Function>}

Function handler for click event on components. If the TreeNode has an onTreeNodeSelectChange handler, this is not fired. See Callback API. Defaults to noop.

onTreeNodeCollapseChange={<Function>}

Function handler for collapse change event on components. See Callback API. Defaults to noop.

onTreeNodeCheckChange={<Function>}

Function handler for checkbox change event on components. See Callback API. Defaults to noop.

onTreeNodeSelectChange={<Function>}

Function handler for select state change event on components. An alternative for cases when checkboxes aren't desired. See Callback API. Defaults to noop.

data={<Array>||<Object>}

The data to use when building components dynamically. Required if there aren't any nested <TreeNode/> elements declared.

Sample array format:


    [{label : "Option 1"},
     {
      label : "Option 2",
      children : [
        {
         checkbox: true,
         label: "Sub Option A",
         children: [{
                     label: "Third Level Nest Option 1",
                     checkbox : true,
                     children : {...},
                   }]
               },
        {
         checkbox: true,
         label: "Sub Option B"
        }]}]

Sample object format:


    {
        "Option 1" : {
          checked: true,
          checkbox: true,
          children: {
            "Sub Option 1" : {
              checked: false
            },
            "Sub Option 2" : {
              checked: false,
              checkbox: true,
              children: {
                "Sub-Sub Option 1" : {
                  checked: false,
                  checkbox: true
                },
                "Sub-Sub Option 2" : {
                  checked: false,
                  checkbox: true
                }
              }
            }
          }
        },
        "Option 2" : {
          checked: false,
          checkbox: true
        }
      }

Callback API for <TreeMenu/> event handler props

<TreeMenu/> callbacks will receive an array representation of the node. Example:


    var onClick = function(node) {

        //node is in format: [<topLevelId>, [...<nodeId>,] <nodeId>]
        //where <nodeId> is the <TreeNode/> that sourced the event
        //...
    }

    return <TreeMenu onTreeNodeClick={onClick} />;

<TreeNode /> Props

label={<String>}

The node label. Required.

checkbox={<Boolean>}

Whether or not the node has a checkbox. Defaults to false. If the node checkbox={true}, clicking on the label also fires the onTreeNodeCheckChange function

checked={<Boolean>}

If the node has a checkbox, whether or not the node is checked. If the node checkbox={true}, clicking on the label also fires the onTreeNodeCheckChange function instead od the onTreeNodeClick function

selected={<Boolean>}

Whether or not the node is selected. An alternative to using checked in conjunction w/ checkbox.

collapsible={<Boolean>}

Whether or not the node is collapsible. If the node has no children, this value has no effect. Defaults to true. This value is overridden by the collapsible prop value set on the root <TreeMenu/>

collapsed={<Boolean>}

If the node is collapsible, whether or not the node is collapsed. Defaults to false.

react-tree-menu's People

Contributors

cwadding avatar mandarinconlabarba avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-tree-menu's Issues

Checkbox not checking in stateful mode when clicking on the checkbox but will when clicking on the label.

I am using stateful mode with my tree coming from a data prop and when I click on the label of a tree node the checkbox associated with it correctly checks and unchecks properly.

When I click on the checkbox itself, the sub-nodes check themselves correctly but the checkbox associated with the node I clicked does not become checked.

Here is my treeMenu

<TreeMenu
    identifier={"id"}
    collapsible={true}
    stateful={true}
    expandIconClass="glyphicon glyphicon-menu-right"
    collapseIconClass="glyphicon glyphicon-menu-down"
    data={data}
    onTreeNodeClick={this.setLastActionState.bind(this, "clicked")} />

Here is my data:

var data = {
    "Show in-plan only": {
        checkbox: true,
        id: "in-plan"
    },
    "Media Type": {
        checkbox: true,
        collapsed: true,
        id: "all-media",
        children: {
            "Third Level Nest Option 1": {
                checkbox : true,
                id: "media-id-1"
            },
            "Third Level Nest Option 2": {
                checkbox : true,
                id: "media-id-2"
            }
        }
    },
    "Status": {
        checkbox: true,
        collapsed: true,
        id: "all-statuses",
        children: {
            "Third Level Nest Option 1": {
                checkbox : true,
                id: "status-id-1"
            },
            "Third Level Nest Option 2": {
                checkbox : true,
                id: "status-id-2"
            }
        }
    }
}

screen shot 2016-05-20 at 9 36 47 am
screen shot 2016-05-20 at 9 37 02 am

update for react 16?

Any way we can get an update for react 16 with the PropTypes fix and remove React.createClass?

License

I see in package.json the license is MIT, but can you add an explicit license file? I can create a PR for that if you don't mind.

How to select just one child at a time?

Hi there.

I'm working on a project that can be summed up by this stack overflow question.

Could you help me modify your code to only allow one child at a time to be selected/highlighted? The basic idea is I'm using your tree menu to recursively build a navigation menu from a WordPress menu built of pages with children and grandchildren. (I'll attach a screenshot of the menu I've built out)
screen shot 2015-07-21 at 11 56 55 am

For example, I'd like to make it so when a user clicks Home -> Getting Started (as seen in the screenshot) ONLY that menu item is selected (if another page was previously selected it should be cleared). Same goes for grandchildren. Ideally, selection of the top level nav items (Home, UPS mobile, mDot) would be disabled.

The flow would be: click Home -> Getting Started -> load page via Ajax to main content area. Then, if another page is selected, clear the menu and start over.

Please let me know if you can help and thank you so much for your tree menu code!

Setting collapsed: true in data breaks stateful tree-menu

I am setting collapsed true in the initial data array. When I render the component I am unable to expand the node. Without setting collapsed true I can expand and collapse as expected.

data= [
  {label: 'node1', collapsed: true, children: [
    {label: 'node2'},
    {label: 'node3'},
  ]}
]

<div>
  <TreeMenu
    stateful={true}
    onTreeNodeClick={onTreeNodeClick}
    onTreeNodeCollapseChange={onTreeNodeCollapseChange}
    onTreeNodeCheckChange={onTreeNodeCheckChange}
    expandIconClass="fa fa-chevron-right"
    collapseIconClass="fa fa-chevron-down"
    data={data} />
</div>

I suspect the stateful collapsed variable is being overwritten by the props collapsed variable in tree_node but couldn't quite figure it out from glancing at the project code.

(Sorry I was signed in as the wrong github user when I first posted this issue!)

Parsing error in Treemenu.jsx and Treenode.jsx

Hi,
I am getting following error in Treemenu.jsx

ERROR in ./~/react-tree-menu/src/TreeMenu.jsx
Module parse failed: C:\ReactJS Workspace\Reactjs-Business-suite\node_modules\react-tree-menu\src\TreeMenu.jsx Unexpected token (5
7:6)

You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected token (57:6)
at Parser.pp.raise (C:\ReactJS Workspace\Reactjs-Business-suite\node_modules\webpack\node_modules\acorn\dist\acorn.js:920:13)
at Parser.pp.unexpected (C:\ReactJS Workspace\Reactjs-Business-suite\node_modules\webpack\node_modules\acorn\dist\acorn.js:14
3:8)
at Parser.pp.parseExprAtom (C:\ReactJS Workspace\Reactjs-Business-suite\node_modules\webpack\node_modules\acorn\dist\acorn.js
330:12)
at Parser.pp.parseExprSubscripts (C:\ReactJS Workspace\Reactjs-Business-suite\node_modules\webpack\node_modules\acorn\dist\ac
rn.js:225:19)
at Parser.pp.parseMaybeUnary (C:\ReactJS Workspace\Reactjs-Business-suite\node_modules\webpack\node_modules\acorn\dist\acorn.
s:204:17)
at Parser.pp.parseExprOps (C:\ReactJS Workspace\Reactjs-Business-suite\node_modules\webpack\node_modules\acorn\dist\acorn.js:
51:19)
at Parser.pp.parseMaybeConditional (C:\ReactJS Workspace\Reactjs-Business-suite\node_modules\webpack\node_modules\acorn\dist
corn.js:133:19)
at Parser.pp.parseMaybeAssign (C:\ReactJS Workspace\Reactjs-Business-suite\node_modules\webpack\node_modules\acorn\dist\acorn
js:110:19)
at Parser.pp.parseParenAndDistinguishExpression (C:\ReactJS Workspace\Reactjs-Business-suite\node_modules\webpack\node_module
\acorn\dist\acorn.js:373:28)
at Parser.pp.parseExprAtom (C:\ReactJS Workspace\Reactjs-Business-suite\node_modules\webpack\node_modules\acorn\dist\acorn.js
304:19)

Error when using React 0.13.x

npm install --save react-tree-menu

npm WARN peerDependencies The peer dependency react@^0.12.2 included from react-tree-menu will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency 
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
npm ERR! Darwin 14.3.0
npm ERR! argv "node" "/usr/local/bin/npm" "install" "--save" "react-tree-menu"
npm ERR! node v0.10.33
npm ERR! npm  v2.9.0
npm ERR! code EPEERINVALID

npm ERR! peerinvalid The package react does not satisfy its siblings' peerDependencies requirements!``` 

Compatible with React 0.14

I get the following error message:

Uncaught Error: Invariant Violation: TreeMenu.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.

NPM Package Not Precompiled

Hi,
When attempting to use this library in our project we were greeted with errors as Babel ignores node_modules during the compilation step.
From what I can tell published npm packages should be precompiled to standard .js format, is there any chance you can republish?

Demo doesn't load some stylesheets in Firefox

In Firefox demo page looks like in the #13 bug screenshot due to failed to load stylesheets.

If I open Firefox debugger console I see:

Blocked loading mixed active content "http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"[Learn More] index.html
Blocked loading mixed active content "http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"[Learn More]

Looks like you published demo when Github pages were served with HTTP, but nowadays all Github pages served only over HTTPS, which leads to "mixed content" issue.

Module parse failed

Trying this package out, won't load. I have dozens of other node modules working correctly in my project, so it's not a webpack issue. Any ideas?

./node_modules/react-tree-menu/src/TreeMenu.jsx
Module parse failed: Unexpected token (57:6)You may need an appropriate loader to handle this file type.
||     return (
|       <div className={props.classNamePrefix}>|         {this._getTreeNodes()}
|       </div>);

Indeterminate Support

Would be great if parent nodes that don't have all their children checked would show up as indeterminate instead of checked.

Make the CSS/Style API better

  • Ability to provide style for everything, not just a css class prefix
  • Ability to pass in style objects, if CSS is not preferred

child node receives incorrect checked state when stateful

Great component by the way! Keep up the good work...

Found this little gem:
If stateful is set to true, and a child node is specified with a checked state different from the state of the parent, then the child node's checked state will be overwritten by the state of the parent.

i.e. given this data:

[
  {
    "label": "Parent 1",
    "checkbox": true,
    "checked": false
  },
  {
    "label": "Parent 2",
    "checkbox": true,
    "checked": true
  },
  {
    "label": "Parent 3",
    "checkbox": true,
    "checked": false,
    "children": [
      {
        "label": "Child 1",
        "checkbox": true,
        "checked": false
      },
      {
        "label": "Child 2",
        "checkbox": true,
        "checked": true
      },
    ],
  },
 ]

Child 2 will actually appear as unchecked.

I believe this is because of this code:

react-tree-menu/src/TreeNode.jsx:129

    if (this._isStateful()) {
      var state = this.state;
      children = React.Children.map(props.children, function (child) {
        return React.cloneElement(child, {
          key: child.key,
          ref: child.ref,
          checked : state.checked  // <-- this is setting checked to the parent state.checked, not the child node's checked state
        })
      });
    }

How to disable tree node checkboxes

I'm trying to disable the all other tree node (Checkboxes) on select anyone of checkbox. But I found that there is no any property (disabled='disabled') to disable the checkbox in document.
Thanks in advance

Propagating a child node's checkbox value to ancestor nodes

As of now, toggling a parent node to be true would toggle all of its children nodes to be also true. However, I would like to propagate a child node's checkbox value back to its ancestor nodes. For example, in your Dynamic (object) demo, toggling Sub-Sub Option 1 to be true should also toggle Sub-Option 1 and Option 1 to be true.

Provided babelified components as part of npm prepublish

Would it be possible, as part of your build/prepublish of this project, to include the transpiled version of your components? I would like to pull in several components into my app, but I don't want to specify a babel-loader (I'm using webpack) to convert things from the node_modules directory.

Make the callback pass 'children' in the key path

In the callbacks pass 'children' in between parent nodes to make the key path mirror the document structure. For example:

[1, 'children', 0]

instead of the current key path format:

[1, 0]

This is more straightforward, and will make it easier to resolve values.

HugeTreeMenu render relay

I got a render delay of more than 150ms when I checked a tree node of tree up to 200 nodes.
Is there any example for huge tree menu?

Problem rendering tree

I get the following error when trying to render a simple tree:

ERROR in .//react-tree-menu/src/TreeMenu.jsx
Module parse failed: ..../node_modules/react-tree-menu/src/TreeMenu.jsx Line 57: Unexpected token <
You may need an appropriate loader to handle this file type.
|
| return (
|


| {this._getTreeNodes()}
|
);
@ .//react-tree-menu/index.js 1:10-39 3:15-44

Code:

import React, {Component} from 'react';
import TreeMenu, {TreeNode, Utils} from 'react-tree-menu';

export default class TreeSelector extends Component {

onTreeNodeClick() {}
onTreeNodeCollapseChange() {}
onTreeNodeCheckChange() {}

render() {
var data = [{
label : "Option 1"
},
{
label : "Option 2",
children : [
{
checkbox: true,
label: "Sub Option A",
children: [
{
label: "Third Level Nest Option 1",
checkbox : true
},
{
label: "Third Level Nest Option 2",
checkbox : true
}
]
},
{
checkbox: true,
label: "Sub Option B"
}
]
}];

  return <TreeMenu
    onTreeNodeClick={this.onTreeNodeClick}
    onTreeNodeCollapseChange={this.onTreeNodeCollapseChange}
    onTreeNodeCheckChange={this.onTreeNodeCheckChange}
    data={data} />;

}
}

Setting collapsed: true in data breaks stateful tree-menu

I am setting collapsed true in the initial data array. When I render the component I am unable to expand the node. Without setting collapsed true I can expand and collapse as expected.

data= [
  {label: 'node1', collapsed: true, children: [
    {label: 'node2'},
    {label: 'node3'},
  ]}
]

<div>
  <TreeMenu
    stateful={true}
    onTreeNodeClick={onTreeNodeClick}
    onTreeNodeCollapseChange={onTreeNodeCollapseChange}
    onTreeNodeCheckChange={onTreeNodeCheckChange}
    expandIconClass="fa fa-chevron-right"
    collapseIconClass="fa fa-chevron-down"
    data={data} />
</div>

I suspect the stateful collapsed variable is being overwritten by the props collapsed variable in tree_node but couldn't quite figure it out from glancing at the project code.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.