Skip to main content

FAQ

How can I listen to form changes in the React standalone component?

When using JSON Forms within your react app, at some point you'll need to access the current form data. For this purpose you can use the onChange prop, which returns the form data and possible validation errors provided by AJV. To get you started, we built two simple examples for you.

The first example showcases a class component:

import React from 'react';
import { JsonForms } from '@jsonforms/react';
import { person } from '@jsonforms/examples';
import { materialRenderers } from '@jsonforms/material-renderers';

const schema = person.schema;
const uischema = person.uischema;
const initialData = person.data;

class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: initialData
};
}

render() {
return (
<div className="App">
<JsonForms
schema={schema}
uischema={uischema}
data={initialData}
renderers={materialRenderers}
onChange={({ errors, data }) => this.setState({data})}
/>
</div>
);
}
}

export default App;

The second example uses the functional component approach. Therefore we use the useState hook, which provides the data (first parameter) and a function to update the data (second parameter).

import React, { useState } from 'react';
import { JsonForms } from '@jsonforms/react';
import { person } from '@jsonforms/examples';
import { materialRenderers } from '@jsonforms/material-renderers';

const schema = person.schema;
const uischema = person.uischema;
const initialData = person.data;

function App() {
const [stateData, setData] = useState(initialData);

return (
<div className="App">
<JsonForms
schema={schema}
uischema={uischema}
data={initialData}
renderers={materialRenderers}
onChange={({ errors, data }) => setData(data)}
/>
</div>
);
}

export default App;

How can I integrate a custom renderer?

Providing a custom renderer gives you full control of the rendered output, enabling you to integrate any custom behavior or pre-built component you'd like. To integrate a custom renderer follow these 3 steps:

  1. Create a custom renderer
  2. Create a tester (which tells JSON Forms for which UI schema element this renderer shall be used)
  3. Register the custom renderer and the tester

Using JSON Forms standalone we register the custom renderer directly on the JSON Forms component:

import { rankWith, scopeEndsWith } from '@jsonforms/core';
import { Rating } from './Rating';

const RatingControl = ({ data, handleChange, path }) => (
<Rating
value={data}
onClick={ev => handleChange(path, Number(ev.value))}
/>
);

<JsonForms
schema={schema}
uischema={uischema}
data={stateData}
renderers={[
...materialRenderers,
//register custom renderer
{ tester: rankWith(3,scopeEndsWith('rating')), renderer: RatingControl }
]}
/>

For more information about custom renderers, have a look here.

How can I use default values within JSON Forms

We use Ajv for handling JSON Schema's default values. To enable the creation of default values, you need to create a custom Ajv instance and hand it over to JSON Forms.

The following example shows the code for React, however the process is the same for Angular and Vue.

import { createAjv } from '@jsonforms/core';

const handleDefaultsAjv = createAjv({useDefaults: true});

<JsonForms
data={data}
schema={schema}
uischema={uischema}
renderers={renderers}
cells={cells}
onChange={({ errors, data }) => setData(data)}
ajv={handleDefaultsAjv}
/>

Now default values within the schema file can be used:

{
"type": "string",
"title": "Name",
"default": "Max"
}

How can I use multipleOf with values smaller than 1?

JSON Forms uses AJV for the validation of data. By default, the multipleOf option of AJV only works with integers. If you are using fractional dividers, you also need to set the multipleOfPrecision option in AJV and pass your AJV instance to JSON Forms. To create the AJV instance with suitable options, you can call the createAjv(options) method exported by JSON Forms Core. AJV suggests setting the multipleOfPrecision to some positive integer N using this formula:

Math.abs(Math.round(multipleOf) - multipleOf) < 1e-N

In the following example multipleOf is set to 0.1 and multipleOfPrecision is set to 2.

const schema = {
price: {
type: 'number',
multipleOf: 0.1
},
};
import { createAjv } from '@jsonforms/core';
import Ajv from 'ajv';

const [ajvInstance] = useState<Ajv>(createAjv({ multipleOfPrecision: 2 }));

<JsonForms
data={data}
schema={schema}
uischema={uischema}
renderers={renderers}
cells={cells}
onChange={({ errors, data }) => setData(data)}
ajv={ajvInstance}
/>