Skip to content
This repository was archived by the owner on Jan 16, 2023. It is now read-only.

Added multi select checkbox functionality #110

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,26 @@ Sets the treeview styling. Defaults to `src/themes/default`.

Sets the treeview animations. Set to `false` if you want to turn off animations. See [velocity-react](https://github.com/twitter-fabric/velocity-react) for more details. Defaults to `src/themes/animations`.

#### enableCheckbox
`PropTypes.bool`
Enable / disable checkbox element for each node. Defaults to `false`.

#### checkboxField
`PropTypes.string`
To set the checkbox field value which need to be used. Defaults to `name`.

#### handleCheckbox
`PropTypes.func`

Callback function when a checbox is checked / unchecked. Passes 2 attributes: the data node and it's checked boolean value.

```
handleCheckbox(node, isChecked) {
node.checked = isChecked;
this.setState({cursor: node});
}
```

#### decorators
`PropTypes.object`

Expand Down Expand Up @@ -157,6 +177,7 @@ const decorators = {
loading: '[optional] boolean',
decorators: '[optional] object',
animations: '[optional] object'
checked: '[optional] boolean'
},
```
#### id
Expand All @@ -179,3 +200,6 @@ Loading flag. It will populate the treeview with the loading component. Useful w

#### decorators / animations
Attach specific decorators / animations to a node. Provides the low level functionality to create visuals on a node-by-node basis. These structures are the same as the top level props, described above.

#### checked
Checked flag. Validate node checkbox should display as checked or not .
19 changes: 17 additions & 2 deletions example/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,14 @@ class DemoTree extends React.Component {
constructor() {
super();

this.state = {data};
this.state = {data, withCheckbox: false};
this.onToggle = this.onToggle.bind(this);
this.withCheckbox = this.withCheckbox.bind(this);
this.handleCheckbox = this.handleCheckbox.bind(this);
}

withCheckbox() {
this.setState({ withCheckbox: !this.state.withCheckbox });
}

onToggle(node, toggled) {
Expand Down Expand Up @@ -78,6 +84,11 @@ class DemoTree extends React.Component {
this.setState({data: filtered});
}

handleCheckbox(node, isChecked) {
node.checked = isChecked;
this.setState({cursor: node});
}

render() {
const {data: stateData, cursor} = this.state;

Expand All @@ -95,9 +106,13 @@ class DemoTree extends React.Component {
</div>
</div>
<div style={styles.component}>
<input type="checkbox" onChange={this.withCheckbox} /> <span style={{ color: '#9da5ab' }}>With Checkbox?</span>
<br />
<Treebeard data={stateData}
decorators={decorators}
onToggle={this.onToggle}/>
onToggle={this.onToggle}
enableCheckbox={this.state.withCheckbox}
handleCheckbox={this.handleCheckbox} />
</div>
<div style={styles.component}>
<NodeViewer node={cursor}/>
Expand Down
31 changes: 29 additions & 2 deletions src/components/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ class TreeNode extends React.Component {
}
}

handleCheckbox(flagChecked) {
if (this.props.handleCheckbox) {
this.props.handleCheckbox(this.props.node, !flagChecked);
}
}

animations() {
const {animations, node} = this.props;

Expand All @@ -44,6 +50,20 @@ class TreeNode extends React.Component {
return Object.assign({}, decorators, nodeDecorators);
}

renderCheckbox(value, style, isChecked) {
if (this.props.enableCheckbox) {
return (
<input
type="checkbox"
checked={isChecked}
value={value}
style={style}
onChange={this.handleCheckbox.bind(this, isChecked)}
/>
);
}
}

render() {
const {style} = this.props;
const decorators = this.decorators();
Expand All @@ -52,6 +72,7 @@ class TreeNode extends React.Component {
return (
<li ref={ref => this.topLevelRef = ref}
style={style.base}>
{this.renderCheckbox(this.props.node[this.props.checkboxField], style.checkbox, this.props.node.checked)}
{this.renderHeader(decorators, animations)}

{this.renderDrawer(decorators, animations)}
Expand Down Expand Up @@ -109,7 +130,10 @@ class TreeNode extends React.Component {
decorators={propDecorators}
key={child.id || index}
node={child}
style={style}/>
style={style}
enableCheckbox={this.props.enableCheckbox}
checkboxField={this.props.checkboxField}
handleCheckbox={this.props.handleCheckbox}/>
)}
</ul>
);
Expand Down Expand Up @@ -144,7 +168,10 @@ TreeNode.propTypes = {
PropTypes.object,
PropTypes.bool
]).isRequired,
onToggle: PropTypes.func
onToggle: PropTypes.func,
enableCheckbox: PropTypes.bool,
checkboxField: PropTypes.string,
handleCheckbox: PropTypes.func
};

export default TreeNode;
14 changes: 11 additions & 3 deletions src/components/treebeard.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ class TreeBeard extends React.Component {
key={node.id || index}
node={node}
onToggle={onToggle}
style={style.tree.node}/>
style={style.tree.node}
enableCheckbox={this.props.enableCheckbox}
checkboxField={this.props.checkboxField}
handleCheckbox={this.props.handleCheckbox}/>
)}
</ul>
);
Expand All @@ -44,13 +47,18 @@ TreeBeard.propTypes = {
PropTypes.bool
]),
onToggle: PropTypes.func,
decorators: PropTypes.object
decorators: PropTypes.object,
enableCheckbox: PropTypes.bool,
checkboxField: PropTypes.string,
handleCheckbox: PropTypes.func
};

TreeBeard.defaultProps = {
style: defaultTheme,
animations: defaultAnimations,
decorators: defaultDecorators
decorators: defaultDecorators,
enableCheckbox: false,
checkboxField: 'name'
};

export default TreeBeard;
7 changes: 6 additions & 1 deletion src/themes/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,19 @@ export default {
fontSize: '14px'
},
node: {
checkbox: {
float: 'left',
marginRight: '5px',
marginTop: '6px'
},
base: {
position: 'relative'
},
link: {
cursor: 'pointer',
position: 'relative',
padding: '0px 5px',
display: 'block'
display: 'inline-block'
},
activeLink: {
background: '#31363F'
Expand Down
11 changes: 11 additions & 0 deletions test/src/components/node-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,4 +298,15 @@ describe('node component', () => {

global.should.not.exist(treeNode.subtreeRef);
});

it('should call handleCheckbox function', () => {
const node = {name: 'test'};
const treeNode = TestUtils.renderIntoDocument(
<TreeNode{...defaults}
node={node}
enableCheckbox={true}
handleCheckbox={() => null}/>
);
treeNode.handleCheckbox();
});
});
7 changes: 7 additions & 0 deletions test/src/components/treebeard-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,11 @@ describe('treebeard component', () => {

nodes.length.should.equal(multipleRootNodes.length);
});

it('should render the treebase with checkbox', () => {
const treebeard = TestUtils.renderIntoDocument(<Treebeard data={defaults} enableCheckbox={true}/>);
const treeBase = treebeard.treeBaseRef;
const elementType = treeBase.children[0].children[0].type;
elementType.toLowerCase().should.equal('checkbox');
});
});