Skip to content

Commit 0b054b5

Browse files
committed
Get children expansion to work
1 parent 2f193d1 commit 0b054b5

File tree

6 files changed

+265
-178
lines changed

6 files changed

+265
-178
lines changed

src/examples/basicExample/app.js

Lines changed: 52 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,80 +5,74 @@ import styles from './stylesheets/app.scss';
55

66
const App = React.createClass({
77
getInitialState() {
8-
return {};
9-
},
10-
render() {
11-
const projectName = 'React Sortable Tree';
12-
const authorName = 'Chris Fritz';
13-
const authorUrl = 'https://github.com/fritz-c';
14-
const githubUrl = 'https://github.com/fritz-c/react-sortable-tree';
15-
16-
const treeData = [
17-
{
18-
key: 'b12314', // string or number. Every key in the tree needs to be unique
19-
value: { // Custom value. Can be anything - object, array, string, etc.
8+
return {
9+
treeData: [
10+
{
2011
id: 'b12314',
2112
title: 'Joe',
2213
subtitle: 'Pancakes',
23-
},
24-
expanded: true,
25-
children: [
26-
{
27-
value: {
14+
expanded: true,
15+
children: [
16+
{
2817
id: 1,
2918
title: 'Really Long Name Nicholas Who Always Got' +
3019
' Picked on in School For His Really Long Name',
3120
subtitle: 'Really good icebreaker, though',
21+
children: [], // null or undefined also ok
22+
},
23+
{
24+
title: 2,
3225
},
33-
children: [], // null or undefined also ok
34-
},
35-
{
36-
value: 2,
37-
},
38-
{
39-
key: 2412,
40-
value: 2,
41-
children: (resolve, _reject) => {
42-
setTimeout(() => {
43-
resolve([
44-
{
45-
key: 1215,
46-
value: 5,
47-
},
48-
{
49-
key: 2125,
50-
value: 215,
51-
},
52-
]);
53-
}, 2000);
26+
{
27+
title: 2,
28+
children: [
29+
{
30+
title: 5,
31+
},
32+
{
33+
title: 215,
34+
},
35+
],
36+
// children: (resolve, _reject) => {
37+
// setTimeout(() => {
38+
// resolve([
39+
// {
40+
// key: 1215,
41+
// value: 5,
42+
// },
43+
// {
44+
// key: 2125,
45+
// value: 215,
46+
// },
47+
// ]);
48+
// }, 2000);
49+
// },
5450
},
55-
},
56-
],
57-
},
58-
{
59-
key: 'b12315',
60-
value: {
51+
],
52+
},
53+
{
6154
id: 'b12315',
6255
title: 'Frank',
6356
},
64-
},
65-
{
66-
key: 'b12316',
67-
value: {
57+
{
6858
id: 'b12316',
6959
title: 'Beast Man',
7060
subtitle: 'Pancakes',
7161
},
72-
},
73-
{
74-
key: 'b12336',
75-
value: {
62+
{
7663
id: 'b12336',
7764
title: 'Tracy Page',
7865
subtitle: 'Waffles',
7966
},
80-
},
81-
];
67+
],
68+
};
69+
},
70+
71+
render() {
72+
const projectName = 'React Sortable Tree';
73+
const authorName = 'Chris Fritz';
74+
const authorUrl = 'https://github.com/fritz-c';
75+
const githubUrl = 'https://github.com/fritz-c/react-sortable-tree';
8276

8377
return (
8478
<div>
@@ -97,10 +91,11 @@ const App = React.createClass({
9791
<h3>Demo</h3>
9892

9993
<SortableTree
100-
treeData={treeData}
94+
treeData={this.state.treeData}
95+
updateTreeData={treeData => this.setState({ treeData })}
10196
generateNodeProps={({
102-
nodeData: _nodeData,
103-
parentPath: _parentPath,
97+
node: _node,
98+
path: _path,
10499
lowerSiblingCounts: _lowerSiblingCounts,
105100
listIndex: _listIndex,
106101
}) => ({

src/node-renderer-default.js

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,17 @@ const NodeRendererDefault = ({
2020
connectDragPreview,
2121
connectDragSource,
2222
isDragging,
23-
nodeData,
23+
node,
24+
path,
25+
treeIndex,
2426
buttons,
2527
}) => (
2628
<div style={{ height: '100%' }}>
27-
{toggleChildrenVisibility && nodeData.children && nodeData.children.length > 0 && (
29+
{toggleChildrenVisibility && node.children && node.children.length > 0 && (
2830
<div
29-
className={nodeData.expanded ? styles.collapseButton : styles.expandButton}
31+
className={node.expanded ? styles.collapseButton : styles.expandButton}
3032
style={{ left: -0.5 * scaffoldBlockPxWidth }}
31-
onClick={toggleChildrenVisibility}
33+
onClick={() => toggleChildrenVisibility({node, path, treeIndex})}
3234
/>
3335
)}
3436

@@ -43,15 +45,15 @@ const NodeRendererDefault = ({
4345
<div className={styles.rowLabel}>
4446
<span
4547
className={styles.rowTitle +
46-
(nodeData.value.subtitle ? ` ${styles.rowTitleWithSubtitle}` : '')
48+
(node.subtitle ? ` ${styles.rowTitleWithSubtitle}` : '')
4749
}
4850
>
49-
{nodeData.value.title}
51+
{node.title}
5052
</span>
5153

52-
{nodeData.value.subtitle &&
54+
{node.subtitle &&
5355
<span className={styles.rowSubtitle}>
54-
{nodeData.value.subtitle}
56+
{node.subtitle}
5557
</span>
5658
}
5759
</div>
@@ -70,9 +72,10 @@ const NodeRendererDefault = ({
7072
);
7173

7274
NodeRendererDefault.propTypes = {
73-
nodeData: PropTypes.object.isRequired,
74-
parentPath: PropTypes.arrayOf(PropTypes.oneOfType([ PropTypes.string, PropTypes.number ])).isRequired,
75-
lowerSiblingCounts: PropTypes.arrayOf(PropTypes.number).isRequired,
75+
node: PropTypes.object.isRequired,
76+
path: PropTypes.arrayOf(PropTypes.oneOfType([ PropTypes.string, PropTypes.number ])).isRequired,
77+
treeIndex: PropTypes.number.isRequired,
78+
lowerSiblingCounts: PropTypes.arrayOf(PropTypes.number).isRequired,
7679

7780
scaffoldBlockPxWidth: PropTypes.number.isRequired,
7881
toggleChildrenVisibility: PropTypes.func,

src/react-sortable-tree.js

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import TreeNode from './tree-node';
1515
import {
1616
getVisibleNodeCount,
1717
getVisibleNodeInfoFlattened,
18+
changeNodeAtPath,
1819
} from './utils/tree-data-utils';
1920
import ItemTypes from './item-types';
2021
import styles from './react-sortable-tree.scss';
@@ -39,24 +40,53 @@ function collect(connect, monitor) {
3940
};
4041
}
4142

43+
function defaultGetNodeKey({ node: _node, treeIndex }) {
44+
return treeIndex;
45+
}
46+
47+
function defaultToggleChildrenVisibility({ node: _node, path, treeIndex: _treeIndex }) {
48+
this.props.updateTreeData(changeNodeAtPath({
49+
treeData: this.props.treeData,
50+
path,
51+
newNode: ({ node }) => ({ ...node, expanded: !node.expanded }),
52+
getNodeKey: this.getNodeKey,
53+
}));
54+
}
55+
4256
class ReactSortableTree extends Component {
4357
constructor(props) {
4458
super(props);
4559

46-
this.state = {
47-
nodeContentRenderer: dragSource(ItemTypes.HANDLE, cardSource, collect)(props.nodeContentRenderer),
48-
key: 'value',
49-
};
60+
if (process.env.NODE_ENV === 'development') {
61+
/* eslint-disable no-console */
62+
const usesDefaultHandlers = (
63+
!props.toggleChildrenVisibility
64+
);
65+
66+
if (!props.updateTreeData && usesDefaultHandlers) {
67+
console.warn('Need to add specify updateTreeData prop if default event handlers are used');
68+
}
69+
/* eslint-enable */
70+
}
71+
72+
// Fall back to default event listeners if necessary and bind them to the tree
73+
this.getNodeKey = (props.getNodeKey || defaultGetNodeKey).bind(this);
74+
this.toggleChildrenVisibility = (
75+
props.toggleChildrenVisibility || defaultToggleChildrenVisibility
76+
).bind(this);
77+
this.nodeContentRenderer = dragSource(ItemTypes.HANDLE, cardSource, collect)(
78+
props.nodeContentRenderer ||
79+
require('./node-renderer-default').default // eslint-disable-line global-require
80+
);
5081
}
5182

5283
render() {
5384
const {
5485
treeData,
5586
rowHeight,
56-
getNodeKey,
5787
} = this.props;
5888

59-
const rows = getVisibleNodeInfoFlattened(treeData, getNodeKey);
89+
const rows = getVisibleNodeInfoFlattened(treeData, this.getNodeKey);
6090

6191
return (
6292
<div style={{ height: '100%' }} className={styles.tree}>
@@ -76,26 +106,27 @@ class ReactSortableTree extends Component {
76106
);
77107
}
78108

79-
renderRow({ node, parentPath, lowerSiblingCounts }, listIndex) {
80-
const NodeContentRenderer = this.state.nodeContentRenderer;
109+
renderRow({ node, path, lowerSiblingCounts }, treeIndex) {
110+
const NodeContentRenderer = this.nodeContentRenderer;
81111
const nodeProps = !this.props.generateNodeProps ? {} : this.props.generateNodeProps({
82-
nodeData: node,
83-
parentPath,
112+
node,
113+
path,
84114
lowerSiblingCounts,
85-
listIndex,
115+
treeIndex,
86116
});
87117

88118
return (
89119
<TreeNode
90-
listIndex={listIndex}
120+
treeIndex={treeIndex}
91121
lowerSiblingCounts={lowerSiblingCounts}
92122
scaffoldBlockPxWidth={this.props.scaffoldBlockPxWidth}
93123
>
94124
<NodeContentRenderer
95-
nodeData={node}
96-
parentPath={parentPath}
125+
node={node}
126+
path={path}
127+
treeIndex={treeIndex}
97128
lowerSiblingCounts={lowerSiblingCounts}
98-
toggleChildrenVisibility={() => 1}
129+
toggleChildrenVisibility={this.toggleChildrenVisibility}
99130
scaffoldBlockPxWidth={this.props.scaffoldBlockPxWidth}
100131
{...nodeProps}
101132
/>
@@ -115,14 +146,14 @@ ReactSortableTree.propTypes = {
115146
nodeContentRenderer: PropTypes.any,
116147
generateNodeProps: PropTypes.func,
117148

118-
getNodeKey: PropTypes.func,
149+
getNodeKey: PropTypes.func,
150+
updateTreeData: PropTypes.func,
151+
toggleChildrenVisibility: PropTypes.func,
119152
};
120153

121154
ReactSortableTree.defaultProps = {
122-
nodeContentRenderer: require('./node-renderer-default').default, // eslint-disable-line global-require
123155
rowHeight: 62,
124156
scaffoldBlockPxWidth: 44,
125-
getNodeKey: (nodeData, treeIndex) => treeIndex,
126157
};
127158

128159
export default dragDropContext(HTML5Backend)(ReactSortableTree);

src/tree-node.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import styles from './tree-node.scss';
33

44
const TreeNode = ({
55
children,
6-
listIndex,
6+
treeIndex,
77
scaffoldBlockPxWidth,
88
lowerSiblingCounts,
99
}) => {
@@ -14,7 +14,7 @@ const TreeNode = ({
1414
if (lowerSiblingCount > 0) {
1515
// At this level in the tree, the nodes had sibling nodes further down
1616

17-
if (listIndex === 0) {
17+
if (treeIndex === 0) {
1818
// Top-left corner of the tree
1919
// +-----+
2020
// | |
@@ -39,7 +39,7 @@ const TreeNode = ({
3939
// +--+--+
4040
lineClass = styles.lineFullVertical;
4141
}
42-
} else if (listIndex === 0) {
42+
} else if (treeIndex === 0) {
4343
// Top-left corner of the tree, but has no siblings
4444
// +-----+
4545
// | |
@@ -80,7 +80,7 @@ const TreeNode = ({
8080
};
8181

8282
TreeNode.propTypes = {
83-
listIndex: PropTypes.number.isRequired,
83+
treeIndex: PropTypes.number.isRequired,
8484
scaffoldBlockPxWidth: PropTypes.number.isRequired,
8585
children: PropTypes.node,
8686
lowerSiblingCounts: PropTypes.array.isRequired,

0 commit comments

Comments
 (0)