react-json-inspector
react-json-inspector copied to clipboard
editable fields
hey, thanks for developing the component :)
my app needs to to display, search and modify json object. do you have anything planned for this? if not, would you accept a proper pull request including such a feature?
Hello, there is already something in place that might help you: each key and primitive property renders a hidden input that could become visible once that block is focused – much like it's done in Chrome DevTools:

To enable that, add the following to your CSS:
.json-inspector__selection {
display: block;
position: absolute;
top: 0;
left: -3px;
right: 0;
z-index: 1;
padding: 0 3px;
font: 11px/1 Menlo, Consolas, monospace;
outline: none;
border: none;
opacity: 0;
box-shadow: 3px 3px 4px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(0, 0, 0, 0.3);
color: #222;
}
.json-inspector__selection:focus {
opacity: 1;
}
The component is located in lib/selection.js, for now it's a readonly input. I believe, it could be extended to handle modification (i.e. save on Enter, discard on blur). On the other hand, we could allow for this sort of extended functionality to be passed as an option to the whole inspector component – much like it's already done for searchBar component. What do you think?
I'd really like to have the same behavior as the dev tools, esp. the response to tabs. I'm certain, you're familiar, but just to be explicit and on the same page:
{
attr : 'val',
attr2 : 'val2'
}
attr is focused / editable. [tab] and now val is editable. another three tabs would create a new key / value pair.
Regarding the read / write, I think it'd be a good idea to not modify the data by default. Similar to how React handles the input values with it's controlled component concept:
<Inspector data={this.state.data} onCommit={this.handleCommit} />
handleCommit(keyPath, value)
You could also enable "in place" editing:
<Inspector defaultData={this.state.data} />
That'd copy the provided JSON object and then modify that directly.
I agree, working tabs would be really nice, need to figure out cheaper solution to that.
Also agree that component should not modify the original data itself, it's better done through intent callbacks, like onCommit. What I'm thinking more about is that we can keep the component less sophisticated if the edition feature is externalised. Imagine that you create your own implementation of Selection component that would accept onCommit callback. Then you compose it with Inspector component and along with that have a parent component that would control both:
// editor.js
// ...
render: function() {
var data = this._getData(); // gets either the original data or the modified one
// FIXME: Figure out a good name for the prop name, callback name and the passed component.
var inputComponent = <CustomInput onSubmit={ this._onCommit } />
return <Inspector data={data} selection={ inputComponent } />
},
_onCommit: function(keypath, changedValue) {
this._setData(
applyPatch(this._getData(), keypath, changedValue)
);
}
As for naming, we can call this component labelInput, sorry this is best I could come up with.
Ok, I think I get your approach and I think that'd also enable all kinds of cool editor fields - any custom element, which is really nice. So whenever a field gets focus, this component will get rendered, receive a value as a prop and then when the editing is done, its onSubmit will be called. Sounds very good to me. :+1:
Added interactiveLabel option in e299f38, pass in component factory that would receive value prop. Released as 5.0.0.
I completely overlooked the fact that I wasn't passing current keypath or any other relevant information to the interactive label. Since 682c7ed it now receives:
value, either stringified property value or key value that is being interacted with,originalValue, either the original property value or key value,isKey, boolean flag to differentiate between interacting with keys or properties,keypath, keypath of the node being interacted with, will be the same for keys and properties
Hope it will help better. Released as 5.0.2.
How is it intended to be used in the above use case? Right now the inputs are always shown when the factory is provided. The onClick handler on the Inspector can't cancel the expansion of a node, so implementing a handler for that is currently not an option.
I suppose you're aware of the fact, that you can't add any new properties to object right now, but I still wanted to mention it, just in case. :)
Thanks for the work so far!
The way I used it before was rendering an invisible, yet focusable input, and revealing it when focused. Check if it works for your case.
As for adding new keys, do you want to mimic the Chrome DevTools interaction (double-click on empty area, Enter or Tab from last available field) or have explicit visual control, e.g. 'Add key' button?
How would they gain focus? The labels wrapping the inputs are targeted at the radios and tabbing through the whole application to eventually focus one of the fields is not really all that user friendly.
For adding new keys I'm fine with either.
I have just put -1 tab index to those radios and pushed a small example on how those inputs can be revealed, (there's some necessary styling): either tab through or click on any field you want to edit. Let me know if I misunderstood something :smile:
Ahhh, no - you understood perfectly, it was me who was a little bit slow. ☺️ Thank you for the example, I'm up and running now.
Hi, there was a bug when updating a property value would not rerender the corresponding node, it's fixed in 5.0.3. Just thinking that this bug could affect the feature you are working on.
Beautiful!