From d0592883c51dd8b98f1dfa105b21448de7dd789f Mon Sep 17 00:00:00 2001 From: Philipp Fritsche Date: Thu, 24 Jun 2021 13:35:14 +0000 Subject: [PATCH] feat: custom validator --- docs/handler/validate.md | 12 +++++++++++- src/form.jsx | 4 +++- src/validate.js | 6 +++--- test/form.jsx | 27 +++++++++++++++++++++++++++ test/validate.js | 2 +- 5 files changed, 45 insertions(+), 6 deletions(-) diff --git a/docs/handler/validate.md b/docs/handler/validate.md index e823aeb..0da3a99 100644 --- a/docs/handler/validate.md +++ b/docs/handler/validate.md @@ -26,4 +26,14 @@ You can provide a translation function to change representation of errors per `a }/> ``` - +You can add errors on top of the schema validation by injecting your own validator. +```jsx +import { finalizeName } from 'liform-react-final' +const myValidator = (values, liformApi) => { + // inspect the values and return a flat error object + return { + [finalizeName('my.object.property')]: 'some error', + } +} + +``` diff --git a/src/form.jsx b/src/form.jsx index e9205f3..df2d985 100644 --- a/src/form.jsx +++ b/src/form.jsx @@ -92,7 +92,8 @@ export function Liform(props) { const onValidate = useMemo(() => buildFlatValidatorHandler(buildFlatValidatorStack( buildFlatAjvValidate(props.ajv, liformApi.schema, props.ajvTranslator || translateAjv), - ), liformApi), [props.ajv, props.ajvTranslator, liformApi]) + ...[props.validate].filter(Boolean), + ), liformApi), [props.ajv, props.ajvTranslator, liformApi, props.validate]) const finalFormProps = { debug: props.debug, @@ -168,6 +169,7 @@ Liform.propTypes = { ajv: PropTypes.func, ajvTranslator: PropTypes.func, + validate: PropTypes.func, ...FinalForm.propTypes, } diff --git a/src/validate.js b/src/validate.js index f22e4d4..96cb0b3 100644 --- a/src/validate.js +++ b/src/validate.js @@ -51,11 +51,11 @@ export const flatAjvValidate = (ajv, schema, ajvTranslate, values) => { } export const buildFlatValidatorStack = (...validators) => { - return (values) => { + return (values, liform) => { const flatErrors = {} for (const validator of validators) { - const newErrors = validator(values) + const newErrors = validator(values, liform) for (const fieldName in newErrors) { flatErrors[fieldName] = (flatErrors[fieldName] || []).concat( Array.isArray(newErrors[fieldName]) ? newErrors[fieldName] : [newErrors[fieldName]], @@ -69,7 +69,7 @@ export const buildFlatValidatorStack = (...validators) => { export const buildFlatValidatorHandler = (flatErrorValidator, liform) => { return (values) => { - const flatErrors = flatErrorValidator(values) + const flatErrors = flatErrorValidator(values, liform) liform.validationErrors = flatErrors return Object.keys(flatErrors).length > 0 ? { [FORM_ERROR]: 'The form has errors - see Liform.validationErrors' } : {} } diff --git a/test/form.jsx b/test/form.jsx index e7da1ca..3f76292 100644 --- a/test/form.jsx +++ b/test/form.jsx @@ -143,4 +143,31 @@ describe('Liform', () => { expect(getLastProps(fieldState).dirty).toBe(false) }) + + it('use custom validator', () => { + const container = jest.fn(() => null) + const theme = { render: { container } } + + const validator = jest.fn(() => ({ + 'foo.bar': 'baz', + })) + + Renderer.create() + + expect(container).toBeCalled() + + Renderer.act(() => { + getLastProps(container).form.registerField('someField', () => null, {}) + getLastProps(container).form.change('someField', 'someValue') + }) + + expect(validator).toBeCalledWith( + {'someField': 'someValue', '_': undefined}, + getLastProps(container).liform, + ) + + expect(getLastProps(container).liform.validationErrors).toEqual({ + 'foo.bar': ['baz'], + }) + }) }) diff --git a/test/validate.js b/test/validate.js index e4480d3..bfc7142 100644 --- a/test/validate.js +++ b/test/validate.js @@ -97,7 +97,7 @@ describe('Flat validator stack', () => { stack(values) for(const f of validators) { - expect(f).toBeCalledWith(values) + expect(f).toBeCalledWith(values, undefined) } })