diff --git a/packages/react/src/JsonForms.tsx b/packages/react/src/JsonForms.tsx index 1106365784..3123261dc2 100644 --- a/packages/react/src/JsonForms.tsx +++ b/packages/react/src/JsonForms.tsx @@ -24,7 +24,7 @@ */ import isEqual from 'lodash/isEqual'; import maxBy from 'lodash/maxBy'; -import React from 'react'; +import React, { useEffect } from 'react'; import AJV from 'ajv'; import RefParser from 'json-schema-ref-parser'; import { UnknownRenderer } from './UnknownRenderer'; @@ -38,6 +38,7 @@ import { OwnPropsOfJsonFormsRenderer, removeId, UISchemaElement, + JsonFormsCore } from '@jsonforms/core'; import { ctxToJsonFormsDispatchProps, JsonFormsStateProvider, useJsonForms } from './JsonFormsContext'; @@ -48,6 +49,10 @@ interface JsonFormsRendererState { resolvedSchema: JsonSchema; } +interface JsonFormsReactProps { + onChange?(state: Pick): void; +} + const hasRefs = (schema: JsonSchema): boolean => { if (schema !== undefined) { return Object.keys(findRefs(schema)).length > 0; @@ -156,9 +161,14 @@ export class JsonFormsDispatchRenderer extends ResolvedJsonFormsDispatchRenderer } } -export const JsonFormsDispatch = (props: OwnPropsOfJsonFormsRenderer) => { +export const JsonFormsDispatch = (props: OwnPropsOfJsonFormsRenderer & JsonFormsReactProps) => { const ctx = useJsonForms(); const { refResolver } = ctxToJsonFormsDispatchProps(ctx, props); + const {data, errors} = ctx.core + useEffect(() => { + props.onChange && props.onChange({ data, errors }); + }, [data, errors]); + return ( { - const { ajv, data, schema, uischema, renderers, refParserOptions } = props; +export const JsonForms = (props: JsonFormsInitStateProps & JsonFormsReactProps) => { + const { ajv, data, schema, uischema, renderers, refParserOptions, onChange } = props; return ( { renderers }} > - + ); }; diff --git a/packages/react/test/renderers/JsonForms.test.tsx b/packages/react/test/renderers/JsonForms.test.tsx index 1a79a62797..e23659ce3b 100644 --- a/packages/react/test/renderers/JsonForms.test.tsx +++ b/packages/react/test/renderers/JsonForms.test.tsx @@ -45,10 +45,15 @@ import RefParser from 'json-schema-ref-parser'; import { StatelessRenderer } from '../../src/Renderer'; import Adapter from 'enzyme-adapter-react-16'; -import { JsonFormsDispatchRenderer, JsonFormsDispatch, JsonForms } from '../../src/JsonForms'; +import { + JsonFormsDispatchRenderer, + JsonFormsDispatch, + JsonForms +} from '../../src/JsonForms'; import { JsonFormsReduxContext, useJsonForms, + withJsonFormsControlProps, JsonFormsStateProvider } from '../../src/JsonFormsContext'; @@ -242,7 +247,7 @@ test('ids should be unique within the same form', () => { - , + ); expect(ids.indexOf('#/properties/foo') > -1).toBeTruthy(); @@ -505,3 +510,83 @@ test('JsonForms should create a JsonFormsStateProvider with initState props', () expect(jsonFormsStateProviderInitStateProp.renderers).toBe(renderers); }); + +test('JsonForms should call onChange handler with new data', () => { + const onChangeHandler = jest.fn(); + const TestInputRenderer = withJsonFormsControlProps(props => ( + props.handleChange('foo', ev.target.value)} /> + )); + + const renderers = [ + { + tester: () => 10, + renderer: TestInputRenderer + } + ]; + const wrapper = mount( + + ); + + wrapper.find('input').simulate('change', { + target: { + value: 'Test Value' + } + }); + + const calls = onChangeHandler.mock.calls; + const lastCallParameter = calls[calls.length - 1][0]; + expect(lastCallParameter.data).toEqual({ foo: 'Test Value' }); + expect(lastCallParameter.errors).toEqual([]); +}); + +test('JsonForms should call onChange handler with errors', () => { + const onChangeHandler = jest.fn(); + const TestInputRenderer = withJsonFormsControlProps(props => ( + props.handleChange('foo', ev.target.value)} /> + )); + + const schema = { + type: 'object', + properties: { + foo: { + type: 'string', + minLength: 5 + } + }, + required: ['foo'] + }; + + const renderers = [ + { + tester: () => 10, + renderer: TestInputRenderer + } + ]; + const wrapper = mount( + + ); + + wrapper.find('input').simulate('change', { + target: { + value: 'xyz' + } + }); + + const calls = onChangeHandler.mock.calls; + const lastCallParameter = calls[calls.length - 1][0]; + expect(lastCallParameter.data).toEqual({ foo: 'xyz' }); + expect(lastCallParameter.errors.length).toEqual(1); + expect(lastCallParameter.errors[0].keyword).toEqual('minLength'); +});