Hi everyone ![]()
Super update!!!
I couldn’t accept having compromises, so here’s the updated and complete guide with ALL THE FEATURES! Images, links, buttons, functions, keyRenderer, highlight, themes, and much more..
JSON of the image above
{
"avatar": "https://i.imgur.com/1bX5QH6.jpg",
"string": "Lorem ipsum dolor sit amet",
"integer": 42,
"url": "new URL('https://example.com')",
"float": 114.514,
"error": "error message",
"warning": "WARNING!",
"bigint": "123456789087654321n",
"undefined": "undefined",
"timer": 1,
"date": "new Date('Tue Sep 13 2022 14:07:44 GMT-0500 (Central Daylight Time)')",
"link": "http://example.com",
"emptyArray": [],
"array": [
31,
19,
810,
"test",
"NaN"
],
"emptyObject": [],
"object": {
"bar": false,
"foo": true,
"last": "null"
},
"emptyMap": "new Map()",
"map": "(() => { const m = new Map(); m.set('foo', 1); m.set('goo', 'hello'); m.set({}, 'world'); return m; })()",
"emptySet": "new Set()",
"set": "new Set([1, 2, 3])",
"loopObject": "(() => { const obj = { foo: 42, goo: 'Lorem Ipsum' }; obj.self = obj; return obj; })()",
"loopArray": "(() => { const obj = { foo: 42, goo: 'Lorem Ipsum' }; obj.self = obj; const arr = [obj]; arr[1] = arr; return arr; })()",
"longArray": "Array.from({ length: 1000 }).map((_, i) => i)",
"nestedArray": {
"1": 2,
"3": 4
},
"superLongString": "1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111",
"function": "function aPlusB (a, b) { return a + b }",
"constFunction": "(function(a, b) { return a + b })",
"anonymousFunction": "(function (a, b) { return a + b })",
"shortFunction": "((arg1, arg2) => console.log(arg1, arg2))",
"shortLongFunction": "((arg1, arg2) => { console.log(arg1, arg2); return '123' })",
"string_number": "1234"
}
Index
1. Setup the WebView
2. renderJsonTree (main function)
3. Themes
4. Highlight Updates
5. KeyRenderer
6. Offline viewer
7. Json Viewer dialog
8. AIA
9. Credits
Setup the WebView
The first thing we do is import the HTML into the assets and set the WebViewer’s homeUrl to http://localhost/ + file_name.html, in this case:
renderJsonTree
The only function we’ll use is WebViewer.EvaluateJS, which will call renderJsonTree from the HTML file and therefore create the structure in our WebViewer.
The dictionary we pass will contain the props, as they’re called in the documentation, which are the viewer’s settings.
The most important prop will be
value, which will contain our JSON/dictionary.
Below is the full props list taken directly from the official documentation.
Props
| Name | Type | Default | Description |
|---|---|---|---|
value |
any |
- | Your input data. Any value, object, Array, primitive type, even Map or Set. |
rootName |
string or false |
“root” | The name of the root value. |
theme |
"light" | "dark" | "auto" | Base16 |
"light" |
Color theme. |
className |
string |
- | Custom class name. |
style |
CSSProperties |
- | Custom style. |
sx |
SxProps |
- | The sx prop lets you style elements inline, using values from the theme. |
indentWidth |
number |
3 | Indent width for nested objects |
keyRenderer |
{when: (props) => boolean} |
- | Customize the rendering of key when keyRenderer.when returns true. Render null in keyRenderer will cause the colons to be hidden. |
valueTypes |
ValueTypes |
- | Customize the definition of data types. See Defining Data Types |
enableAdd |
boolean |(path, currentValue) => boolean |
false |
Whether enable add feature. Provide a function to customize this behavior by returning a boolean based on the value and path. |
enableDelete |
boolean |(path, currentValue) => boolean |
false |
Whether enable delete feature. Provide a function to customize this behavior by returning a boolean based on the value and path. |
enableClipboard |
boolean |
false |
Whether enable clipboard feature. |
editable |
boolean |(path, currentValue) => boolean |
false |
Whether enable edit feature. Provide a function to customize this behavior by returning a boolean based on the value and path. |
onChange |
(path, oldVal, newVal) => void |
- | Callback when value changed. |
onCopy |
(path, value) => void |
- | Callback when value copied, you can use it to customize the copy behavior. *Note: you will have to write the data to the clipboard by yourself. |
onSelect |
(path, value) => void |
- | Callback when value selected. |
onAdd |
(path) => void |
- | Callback when the add button is clicked. This is the function which implements the add feature. Please see the DEMO for more details. |
onDelete |
(path) => void |
- | Callback when the delete button is clicked. This is the function which implements the delete feature. Please see the DEMO for more details. |
defaultInspectDepth |
number |
5 | Default inspect depth for nested objects. * If the number is set too large, it could result in performance issues. |
defaultInspectControl |
(path, currentValue) => boolean |
- | Whether expand or collapse a field by default. Using this will override defaultInspectDepth. |
maxDisplayLength |
number |
30 | Hide items after reaching the count.Array and Object will be affected.* If the number is set too large, it could result in performance issues. |
groupArraysAfterLength |
number |
100 | Group arrays after reaching the count. Groups are displayed with bracket notation and can be expanded and collapsed by clicking on the brackets. |
collapseStringsAfterLength |
number |
50 | Cut off the string after reaching the count. Collapsed strings are followed by an ellipsis. String content can be expanded and collapsed by clicking on the string value. |
objectSortKeys |
boolean |
false |
Whether sort keys through String.prototype.localeCompare() |
quotesOnKeys |
boolean |
true |
Whether add quotes on keys. |
displayDataTypes |
boolean |
true |
Whether display data type labels. |
displaySize |
boolean |(path, currentValue) => boolean |
true |
Whether display the size of Object, Array, Map and Set. Provide a function to customize this behavior by returning a boolean based on the value and path. |
displayComma |
boolean |
true |
Whether display commas at the end of the line. |
highlightUpdates |
boolean |
true |
Whether to highlight updates. |
How onChange, onCopy, onSelect, onAdd and onDelete works?
Unlike the other props that receive strings, numbers, and booleans, these ones receive a function that allows communication with Kodular through WebViewStringChange.
Each of these props needs to be enabled with another prop, below the association.
onChange >> editable
onCopy >> enableClipboard
onSelect >> not necessary
onAdd >> enableAdd
onDelete >> enableDelete
I’ll explain only onChange since they all work the same way but with different functions.
We will assign this function as the value for the onChange key.
(path, oldVal, newVal) => window.Kodular.setWebViewString(JSON.stringify({action: ‘onChange’, path: path, oldVal: oldVal, newVal: newVal}))
This will trigger the WebView.WebViewStringChange event, passing a json containing something like:
{
"action": "onChange",
"path": "path of the change",
"oldVal": "old value",
"newVal": "new value"
}
So, every time a value in the tree is modified by the user, WebViewStringChange will be triggered, giving us a way to understand how the user interacted with the WebView/structure.
WebView.WebViewStringChange
Here all the available props as a dictionary
Themes
This magnificent script also allows us to use Base16 themes, and to use them we simply need to pass a dictionary wrapped in () into the theme prop.
In the project at the end of the guide, in the themes variable, you will find some themes I found online.
Nothing stops you from creating your own custom one!
Highlight Updates
This feature has been my nemesis throughout the entire project, and I’m glad to say that now you just need to enable
highlightUpdates in the props and you’re done! KeyRenderer

In addition to the classic struck-through float enabled by the value 114.514, I experimented and managed to achieve different effects, for example,
if value contains the word “error” it underlines and colors the key in red
This is possible thanks to a function in the html that provides the correct formatting based on certain conditions.
To enable the keyRenderer, you just need to pass a pair in the prop dictionary.
![]()
For explanations about the HTML file, I’ll wait for questions to avoid making the guide too heavy
Offline viewer
To obtain the viewer offline, It was enough to simply download the libraries and adapt the HTML code, for you it will be a bit easier
just import all the files
json-viewer-offline.html
react-min.js
react-dom-min.js
json-viewer-mod.js
into the asset
For explanations about the HTML file, I’ll wait for questions to avoid making the guide too heavy
Json Viewer dialog
I think it’s fairly self-explanatory
AIA
json_viewer.aia (15.7 KB)
json-viewer.html (5.1 KB)
json_viewer_offline.aia (108.8 KB)
json-viewer-offline.html (4.8 KB)
offline json-viewer files.zip (91.9 KB)















