Mendix JsonForms Render for Native
JSON Forms is a declarative framework for efficiently building form-based web UIs. These UIs are targeted at entering, modifying and viewing data and are usually embedded within an application.
Implements features from the JSON Forms library in a mendix widget
Studio Pro 11.12 or higher.
Version 2.0.0 is built against Mendix Pluggable Widgets Tools 11.12 (React 19, React
Native 0.84) and is not backward compatible. Stay on the 1.x release for Studio Pro 10.
The date control uses @react-native-community/datetimepicker, pinned to 8.6.0 to match the
version the Mendix native template already links. It ships inside the .mpk, so no change to
the app template is needed, but the pin should be kept in step with the template to avoid two
versions of the same native module.
2.0.0 — added a date control for schema properties declaring format: date. Rebuilt for Studio Pro 11.12. The vendored theme was trimmed to the files the
widget actually uses and converted to TypeScript; unused dependencies were removed.
The widget id also changed, from io.entidad.widget.native.jsonforms.JsonForms to
entidad.io.native.jsonforms.JsonForms, bringing it in line with the other Entidad native
widgets. Studio Pro treats a changed id as a different widget, so a page using the previous
version will not pick this one up: remove the old widget from the page, add this one, and map
the attributes again.
1.0.18 — last release for Studio Pro 10.
Download one of the releases or build from source as follows
git clone https://github.com/Entidad/mendix-react-native-jsonforms.git
cd ./mendix-react-native-jsonforms
npm install
npm run build
Deploy entidad.io.native.JsonForms.mpk to $PROJ/widgets, then run
Synchronize App Directory in Studio Pro (F4, or Menu / App / Synchronize App Directory).
Place the widget in a Data view and map the attributes below.
| Property | Type | Required | Description |
|---|---|---|---|
mxSchema |
String attribute | yes | The JSON Schema describing the form's data. |
mxUiSchema |
String attribute | yes | The UI Schema describing the form's layout. |
mxFormData |
String attribute | yes | Holds the form data. Written as the user edits. |
mxI18nData |
String attribute | yes | Translatable strings for the form, per language. |
mxLanguage |
String attribute | yes | Code of the language to display the form in. |
mxReadOnly |
Boolean attribute | yes | Render values without allowing edits. |
mxStyleData |
Expression | no (default '{}') |
Style JSON, described under Styling below. |
onChangeAction |
Action | no | Runs when the form data changes. |
debugon |
Boolean | yes (default false) |
Write messages to the console. |
The following native controls are implemented
src/renderer/controls/TextControl.tsxsrc/renderer/controls/DateControl.tsxsrc/renderer/controls/CheckBoxControl.tsxsrc/renderer/controls/CheckGroupControl.tsxsrc/renderer/controls/IntegerControl.tsxsrc/renderer/controls/NumberControl.tsxsrc/renderer/controls/PasswordControl.tsxsrc/renderer/controls/RadioControl.tsxsrc/renderer/controls/ReadOnlyControl.tsxsrc/renderer/controls/TextAreaControl.tsxsrc/renderer/controls/UnknownControl.tsx
Compile time styling can be customized by editing src/theme/theme/native/custom-variables.ts. Modeling time styling can be achieved by editing the UI / Style JSON field. A sample style can be found at styles/sample.json
The main container around the widget can be styled as follows
JSON
{
"jsonformsControlsContainer": {
"viewControl":{
"marginLeft": 0,
"marginTop": 0,
"marginBottom": 0,
"marginRight": 0,
"flexDirection": "column"
}
}
}
Each component has a wrapper that can be styled as follows
JSON
{
"jsonformsControlContainer": {
"marginTop": 0,
"marginBottom": 0,
"paddingTop": 0,
"paddingBottom": 0,
"borderColor": "#FF0000"
"borderTopWidth": 0,
"borderBottomWidth": 0
}
}
Here follows some styling samples for the various components.
JSON
{
"input": {
"label": {
"numberOfLines": 1,
"color": "#FF0000",
"fontSize": 14,
"textAlign": "left",
"fontFamily": "Lato-Bold",
"marginTop": 24,
"marginBottom": 8
},
"input": {
"color": "#FF0000",
"borderColor": "#FF0000",
"backgroundColor": "#FF0000",
"selectionColor": "#FF0000",
"placeholderTextColor": "#FF0000",
"fontSize": 14,
"fontFamily": "Lato-Regular",
"lineHeight": 14,
"borderWidth": 1,
"borderRadius": 12,
"minWidth": 48,
"minHeight": 48,
"paddingVertical": 8,
"paddingHorizontal": 8
},
"inputError": {
"color": "#FF0000",
"borderColor": "#FF0000",
"placeholderTextColor": "#FF0000",
"backgroundColor": "#FF0000"
},
"itemContainer": {
"paddingVertical": 12,
"paddingHorizontal": 8,
"backgroundColor": "#FFFFFF"
}
}
}
JSON
{
"input": {
"label": {
"numberOfLines": 1,
"color": "#201313",
"fontSize": 14,
"textAlign": "left",
"fontFamily": "Lato-Bold",
"marginTop": 24,
"marginBottom": 8
},
"labelDisabled": {
"color": "#0A1325"
},
"input": {
"color": "#201313",
"borderColor": "#cdcdcd",
"backgroundColor": "#FFFFFF",
"selectionColor": "#cdcdcd",
"placeholderTextColor": "#a6a6a6",
"fontSize": 14,
"fontFamily": "Lato-Regular",
"lineHeight": 14,
"borderWidth": 1,
"borderRadius": 12,
"minWidth": 48,
"minHeight": 48,
"paddingVertical": 8,
"paddingHorizontal": 8
},
"inputError": {
"color": "#FF0000",
"borderColor": "#FF0000",
"placeholderTextColor": "#FF0000",
"backgroundColor": "#FF0000"
}
}
}
JSON
{
"checkboxControl":{
"caption":{
"color":"#FF0000",
"fontSize": 14,
"fontFamily": "Lato-Regular",
"textAlign": "left"
},
"checkboxInput": {
"color": "#FF0000",
"size": 20,
"backgroundColor": "#FF0000",
"borderColor": "#FF0000",
"borderWidth": 1,
"borderRadius": 8,
"width": 40,
"height": 40
},
"labelContainer": {
"flex":1,
"marginTop":0,
"marginLeft":8
}
}
"input": {
"label": {
"numberOfLines": 1,
"color": "#FF0000",
"fontSize": 14,
"textAlign": "left"
},
"inputError": {
"color": "#FF0000",
"borderColor": "#FF0000",
"placeholderTextColor": "#FF0000",
"backgroundColor": "#FF0000"
}
}
}
JSON
{
"checkboxControl": {
"caption":{
"color":"#FF0000",
"fontSize": 14,
"fontFamily": "Lato-Regular",
"textAlign": "left"
},
"container": {
"flexDirection": "row",
"alignItems": "center",
"height": 35,
"marginTop": 20,
"marginBottom": 20
},
"checkboxInput": {
"color": "#FF0000",
"size": 20,
"backgroundColor": "#FF0000",
"borderColor": "#FF0000",
"borderWidth": 1,
"borderRadius": 8,
"width": 40,
"height": 40
},
"labelContainer": {
"flex":1,
"marginTop":0,
"marginLeft":8
}
},
"input": {
"label": {
"numberOfLines": 1,
"color": "#FF0000"
"fontSize": 8,
"textAlign": "left"
},
"inputError": {
"color": "#FF0000",
"borderColor": "#FF0000",
"placeholderTextColor": "#FF0000",
"backgroundColor": "#FF0000"
}
}
}
JSON
{
"input": {
"label": {
"numberOfLines": 1,
"color": "#FF0000"
"fontSize": 8,
"textAlign": "left"
},
"input": {
"color": "#FF0000",
"borderColor": "#FF0000",
"backgroundColor": "#FF0000",
"selectionColor": "#FF0000",
"placeholderTextColor": "#FF0000",
"fontSize": 8,
"lineHeight": 8,
"borderWidth": 8,
"borderRadius": 8,
"minWidth": 48,
"minHeight": 48,
"paddingVertical": 8,
"paddingHorizontal": 8
},
"inputError": {
"color": "#FF0000",
"borderColor": "#FF0000",
"placeholderTextColor": "#FF0000",
"backgroundColor": "#FF0000"
}
}
}
A radio control is styled through radioButtons for the buttons themselves and input for the
surrounding label, which are the two keys the control merges.
JSON
{
"radioButtons": {
"caption": {
"numberOfLines": 1,
"color": "#201313",
"fontSize": 14,
"fontFamily": "Lato-Regular",
"lineHeight": 20,
"marginBottom": 8,
"marginLeft": 8,
"marginTop": 8
},
"outerCircle": {
"height": 40,
"width": 40,
"borderRadius": 20,
"borderWidth": 1,
"borderColor": "#CCCCCC",
"alignItems": "center",
"justifyContent": "center"
},
"innerCircle": {
"height": 32,
"width": 32,
"borderRadius": 16,
"backgroundColor": "#622C6D"
},
"radioButtonItemContainerStyle": {
"marginBottom": 8
}
}
}
radioButtons also accepts a radioButtonError key, applied when the value fails validation.
It is not set above, so an invalid radio falls back to the built-in danger colours rather than
your own palette.
A date question is rendered as a tappable field that opens the platform's own date picker.
The field is styled through input, the same key the text controls use — the picker itself is
drawn by the operating system and takes no styling from the widget.
JSON
{
"input": {
"label": {
"numberOfLines": 1,
"color": "#201313",
"fontSize": 14,
"fontFamily": "Lato-Bold",
"marginTop": 24,
"marginBottom": 8
},
"input": {
"color": "#201313",
"borderColor": "#cdcdcd",
"backgroundColor": "#FFFFFF",
"fontSize": 14,
"borderWidth": 1,
"borderRadius": 12,
"minHeight": 48,
"paddingVertical": 8,
"paddingHorizontal": 8
},
"inputError": {
"color": "#FF0000",
"borderColor": "#FF0000"
}
}
}
A date question must declare format in the JSON Schema. Without it the property is an
ordinary string and renders as a text input:
"qstDate_1718370d-dfc3-4068-b42c-4716980fd16c": {
"title": "What year did you graduate high school?",
"type": "string",
"format": "date"
}
format may be date or date-time. Values are held as RFC 3339 full dates — 1993-11-23,
not 11/23/1993 — which is what format: date requires and what the bundled ajv-formats
validates against. The date shown to the user is formatted for the device locale; only the
stored value is ISO.
JSON
{
"readOnlyControl": {
"label": {
"fontSize": 12,
"fontWeight": "bold",
"color": "#FFFFFF88"
},
"value": {
"fontSize": 16,
"fontWeight": "normal",
"color": "#FFFFFF",
"marginBottom": 8
},
"container": {
"borderBottomColor": "#FFFFFF44",
"borderBottomWidth": 2
}
}
}
Some styling is baked in at build time rather than set through the Style JSON. It comes from a small copy of a stock Mendix theme kept in the source tree:
src/theme/theme/native/custom-variables.ts— the design tokens the controls readsrc/theme/theme/native/exclusion-variables.tssrc/theme/themesource/atlas_core/native/api.tsand the three helper functions it uses
To change the compiled styling, edit src/theme/theme/native/custom-variables.ts and rebuild.
These files are vendored from a stock Mendix project and are marked @ts-nocheck, since they
are not maintained here. Only the files above are kept: the rest of the copied theme was
unreachable from the widget and was removed in 2.0.0, along with the web assets — stylesheets,
fonts and images — that came with it.
Widget-specific styles such as radioButtons, checkboxControl, readOnlyControl,
jsonformsControlsContainer and jsonformsControlContainer are defined in
src/renderer/theme/widget-variables.ts.
Currently there is no demo project
- Install NPM package dependencies by using:
npm install. Node 20.19.4 or higher is required. - Run
npm startto watch for code changes. On every change:- the widget will be bundled;
- the bundle will be included in a
distfolder in the root directory of the project; - the bundle will be included in the
deploymentandwidgetsfolder of the Mendix test project.
Contributions welcome






