Skip to content

Commit 5dfcfb0

Browse files
committed
Add additional metadata to the targetNode of the event handlers
Resolves #122.
1 parent 34dd87c commit 5dfcfb0

File tree

5 files changed

+113
-13
lines changed

5 files changed

+113
-13
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
### New Features
66

7-
* [#116]: Add `id` property
7+
* [#116]: Add `id` property to specify the DOM ID for the generated tree nodes
8+
* [#122]: Add `label`, `isLeaf`, `isParent`, `parent`, `treeDepth`, and `level` metadata to the target node of `onCheck`, `onClick`, and `onExpand` handlers
89

910
### Bug Fixes
1011

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,11 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
156156
| `showExpandAll` | bool | If true, buttons for expanding and collapsing all parent nodes will appear in the tree. | `false` |
157157
| `showNodeIcon` | bool | If true, each node will show a parent or leaf icon. | `true` |
158158
| `showNodeTitle` | bool | If true, the `label` of each node will become the `title` of the resulting DOM node. Overridden by `node.title`. | `false` |
159-
| `onCheck` | function | onCheck handler: `function(checked) {}` | `() => {}` |
160-
| `onClick` | function | onClick handler: `function(clicked) {}`. If set, it will be called when clicked on a node label. | `() => {}` |
161-
| `onExpand` | function | onExpand handler: `function(expanded) {}` | `() => {}` |
159+
| `onCheck` | function | onCheck handler: `function(checked, targetNode) {}` | `() => {}` |
160+
| `onClick` | function | onClick handler: `function(targetNode) {}`. If set, `onClick` will be called when a node's label has been clicked. | `() => {}` |
161+
| `onExpand` | function | onExpand handler: `function(expanded, targetNode) {}` | `() => {}` |
162+
163+
#### `onCheck` and `onExpand`
162164

163165
#### Node Properties
164166

src/js/CheckboxTree.js

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ class CheckboxTree extends React.Component {
9494

9595
this.onCheck = this.onCheck.bind(this);
9696
this.onExpand = this.onExpand.bind(this);
97+
this.onNodeClick = this.onNodeClick.bind(this);
9798
this.onExpandAll = this.onExpandAll.bind(this);
9899
this.onCollapseAll = this.onCollapseAll.bind(this);
99100
}
@@ -127,7 +128,7 @@ class CheckboxTree extends React.Component {
127128
const node = model.getNode(nodeInfo.value);
128129

129130
model.toggleChecked(nodeInfo, nodeInfo.checked, noCascade);
130-
onCheck(model.serializeList('checked'), { ...nodeInfo, children: node.self.children });
131+
onCheck(model.serializeList('checked'), { ...node, ...nodeInfo });
131132
}
132133

133134
onExpand(nodeInfo) {
@@ -136,7 +137,15 @@ class CheckboxTree extends React.Component {
136137
const node = model.getNode(nodeInfo.value);
137138

138139
model.toggleNode(nodeInfo.value, 'expanded', nodeInfo.expanded);
139-
onExpand(model.serializeList('expanded'), { ...nodeInfo, children: node.self.children });
140+
onExpand(model.serializeList('expanded'), { ...node, ...nodeInfo });
141+
}
142+
143+
onNodeClick(nodeInfo) {
144+
const { onClick } = this.props;
145+
const { model } = this.state;
146+
const node = model.getNode(nodeInfo.value);
147+
148+
onClick({ ...node, ...nodeInfo });
140149
}
141150

142151
onExpandAll() {
@@ -194,7 +203,6 @@ class CheckboxTree extends React.Component {
194203
optimisticToggle,
195204
showNodeTitle,
196205
showNodeIcon,
197-
onClick,
198206
} = this.props;
199207
const { id, model } = this.state;
200208
const { icons: defaultIcons } = CheckboxTree.defaultProps;
@@ -239,7 +247,7 @@ class CheckboxTree extends React.Component {
239247
treeId={id}
240248
value={node.value}
241249
onCheck={this.onCheck}
242-
onClick={onClick}
250+
onClick={this.onNodeClick}
243251
onExpand={this.onExpand}
244252
>
245253
{children}

src/js/NodeModel.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,30 @@ class NodeModel {
2020
return this.flatNodes[value];
2121
}
2222

23-
flattenNodes(nodes, parent = {}) {
23+
flattenNodes(nodes, parent = {}, depth = 0) {
2424
if (!Array.isArray(nodes) || nodes.length === 0) {
2525
return;
2626
}
2727

2828
const { disabled, noCascade } = this.props;
2929

3030
// Flatten the `node` property for internal lookups
31-
nodes.forEach((node) => {
31+
nodes.forEach((node, index) => {
3232
const isParent = this.nodeHasChildren(node);
3333

3434
this.flatNodes[node.value] = {
35-
self: node,
35+
label: node.label,
36+
value: node.value,
37+
children: node.children,
3638
parent,
3739
isParent,
3840
isLeaf: !isParent,
3941
showCheckbox: node.showCheckbox !== undefined ? node.showCheckbox : true,
4042
disabled: this.getDisabledState(node, parent, disabled, noCascade),
43+
treeDepth: depth,
44+
index,
4145
};
42-
this.flattenNodes(node.children, node);
46+
this.flattenNodes(node.children, node, depth + 1);
4347
});
4448
}
4549

@@ -113,7 +117,7 @@ class NodeModel {
113117
this.toggleNode(node.value, 'checked', isChecked);
114118
} else {
115119
// Percolate check status down to all children
116-
flatNode.self.children.forEach((child) => {
120+
flatNode.children.forEach((child) => {
117121
this.toggleChecked(child, isChecked, noCascade);
118122
});
119123
}

test/CheckboxTree.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,4 +593,89 @@ describe('<CheckboxTree />', () => {
593593
assert.equal('jupiter', actualNode.value);
594594
});
595595
});
596+
597+
describe('handler.targetNode', () => {
598+
it('should supply a variety of metadata relating to the target node', () => {
599+
let checkNode = null;
600+
let expandNode = null;
601+
let clickNode = null;
602+
603+
const getNodeMetadata = (node) => {
604+
const {
605+
value,
606+
label,
607+
isLeaf,
608+
isParent,
609+
treeDepth,
610+
index,
611+
parent: { value: parentValue },
612+
} = node;
613+
614+
return {
615+
value,
616+
label,
617+
isLeaf,
618+
isParent,
619+
treeDepth,
620+
index,
621+
parentValue,
622+
};
623+
};
624+
const wrapper = mount(
625+
<CheckboxTree
626+
expanded={['jupiter']}
627+
checked={[]}
628+
nodes={[
629+
{
630+
value: 'jupiter',
631+
label: 'Jupiter',
632+
children: [
633+
{ value: 'io', label: 'Io' },
634+
{ value: 'europa', label: 'Europa' },
635+
],
636+
},
637+
]}
638+
onCheck={(checked, node) => {
639+
checkNode = node;
640+
}}
641+
onClick={(node) => {
642+
clickNode = node;
643+
}}
644+
onExpand={(expanded, node) => {
645+
expandNode = node;
646+
}}
647+
/>,
648+
);
649+
const expectedLeafMetadata = {
650+
value: 'io',
651+
label: 'Io',
652+
isLeaf: true,
653+
isParent: false,
654+
treeDepth: 1,
655+
index: 0,
656+
parentValue: 'jupiter',
657+
};
658+
const expectedParentMetadata = {
659+
value: 'jupiter',
660+
label: 'Jupiter',
661+
isLeaf: false,
662+
isParent: true,
663+
treeDepth: 0,
664+
index: 0,
665+
parentValue: undefined,
666+
};
667+
668+
// onCheck
669+
wrapper.find('TreeNode').at(1).find('input[type="checkbox"]').simulate('click');
670+
assert.deepEqual(expectedLeafMetadata, getNodeMetadata(checkNode));
671+
672+
// onClick
673+
wrapper.find('TreeNode').at(1).find('.rct-node-clickable').simulate('click');
674+
assert.deepEqual(expectedLeafMetadata, getNodeMetadata(clickNode));
675+
676+
// onExpand
677+
wrapper.find('TreeNode').at(0).find('Button.rct-collapse-btn').simulate('click');
678+
assert.deepEqual(expectedParentMetadata, getNodeMetadata(expandNode));
679+
});
680+
});
596681
});

0 commit comments

Comments
 (0)