diff --git a/README.md b/README.md index db36046..92e4946 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,9 @@ For `labelRenderer`, you can provide a full path - [see this PR](https://github. - `shouldExpandNode: function(keyName, data, level)` - determines if node should be expanded (root is expanded by default) - `hideRoot: Boolean` - if `true`, the root node is hidden. - `sortObjectKeys: Boolean | function(a, b)` - sorts object keys with compare function (optional). Isn't applied to iterable maps like `Immutable.Map`. +- `onNodeExpansionChanging: function(keyName, data, level, expanded)` - invoked when a node is expanding or collapsing. +- `onNodeExpansionChanged: function(keyName, data, level, expanded)` - invoked when a node is expanded or collapsed. +- `isNodeExpansionDynamic: Boolean` - if `true`, `shouldExpandNode` will be called each render to determine the expansion state of a node, rather than just once during mount ### Credits diff --git a/examples/src/App.js b/examples/src/App.js index be68c26..5bfc644 100755 --- a/examples/src/App.js +++ b/examples/src/App.js @@ -158,6 +158,24 @@ const App = () => ( shouldExpandNode={() => false} /> +

Expansion Notifications

+
+ false} + onNodeExpansionChanging={ + (keyPath, data, level, expanded) => { + console.log(`Node ${expanded ? 'expanding' : 'collapsing'}: ${keyPath}`); + } + } + onNodeExpansionChanged={ + (keyPath, data, level, expanded) => { + console.log(`Node ${expanded ? 'expanded' : 'collapsed'}: ${keyPath}`); + } + } + /> +
); diff --git a/package.json b/package.json index b53cd2c..5c3cc66 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ "author": "Shu Uesugi (http://github.com/chibicode)", "contributors": [ "Dave Vedder (http://www.eskimospy.com/)", - "Daniele Zannotti (http://www.github.com/dzannotti)" + "Daniele Zannotti (http://www.github.com/dzannotti)", + "Phillip Hoff (http://www.github.com/philliphoff)" ], "license": "MIT", "bugs": { diff --git a/src/JSONNestedNode.js b/src/JSONNestedNode.js index 2edf6de..017270a 100644 --- a/src/JSONNestedNode.js +++ b/src/JSONNestedNode.js @@ -76,7 +76,10 @@ export default class JSONNestedNode extends React.Component { level: PropTypes.number.isRequired, sortObjectKeys: PropTypes.oneOfType([PropTypes.func, PropTypes.bool]), isCircular: PropTypes.bool, - expandable: PropTypes.bool + expandable: PropTypes.bool, + onNodeExpansionChanging: PropTypes.func, + onNodeExpansionChanged: PropTypes.func, + isNodeExpansionDynamic: PropTypes.bool }; static defaultProps = { @@ -98,7 +101,7 @@ export default class JSONNestedNode extends React.Component { }; } - shouldComponentUpdate = shouldPureComponentUpdate; + shouldComponentUpdate = this.props.isNodeExpansionDynamic ? undefined : shouldPureComponentUpdate; render() { const { @@ -114,7 +117,13 @@ export default class JSONNestedNode extends React.Component { labelRenderer, expandable } = this.props; - const expanded = this.state.expanded; + const expanded = + this.props.isNodeExpansionDynamic + && this.props.shouldExpandNode + && !this.props.isCircular + ? this.props.shouldExpandNode(this.props.keyPath, this.props.data, this.props.level) + : this.state.expanded; + const renderedChildren = expanded || (hideRoot && this.props.level === 0) ? renderChildNodes({ ...this.props, level: this.props.level + 1 }) : null; @@ -131,6 +140,30 @@ export default class JSONNestedNode extends React.Component { ); const stylingArgs = [keyPath, nodeType, expanded, expandable]; + const handleClick = () => { + const newState = !expanded; + + if (this.props.onNodeExpansionChanging) { + this.props.onNodeExpansionChanging( + this.props.keyPath, + this.props.data, + this.props.level, + newState); + } + + this.setState( + { expanded: newState }, + () => { + if (this.props.onNodeExpansionChanged) { + this.props.onNodeExpansionChanged( + this.props.keyPath, + this.props.data, + this.props.level, + this.state.expanded); + } + }); + }; + return hideRoot ? (
    • @@ -144,18 +177,18 @@ export default class JSONNestedNode extends React.Component { styling={styling} nodeType={nodeType} expanded={expanded} - onClick={this.handleClick} + onClick={handleClick} /> } {renderedItemString} @@ -165,6 +198,4 @@ export default class JSONNestedNode extends React.Component { ); } - - handleClick = () => this.setState({ expanded: !this.state.expanded }); }