Skip to content

Commit c17dfb8

Browse files
authored
Merge pull request #568 from rvsia/fixValidatorFunc
fix(renderer): memoize do not pass all arguments
2 parents ba06e2b + 95b4187 commit c17dfb8

File tree

6 files changed

+70
-10
lines changed

6 files changed

+70
-10
lines changed
Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
const composeValidators = (validators = []) => (value, allValues) => {
1+
const composeValidators = (validators = []) => (value, allValues, meta) => {
22
const [initialValidator, ...sequenceValidators] = validators;
3-
const resolveValidator = (error, validator) => error || (typeof validator === 'function' ? validator(value, allValues) : undefined);
3+
const resolveValidator = (error, validator) => error || (typeof validator === 'function' ? validator(value, allValues, meta) : undefined);
44
if (initialValidator && typeof initialValidator === 'function') {
5-
const result = initialValidator(value, allValues);
5+
const result = initialValidator(value, allValues, meta);
66
if (result && result.then) {
77
return result.then(() => sequenceValidators.reduce(resolveValidator, undefined)).catch((error) => error);
88
}
99
}
1010

11-
return validators.reduce((error, validator) => error || (typeof validator === 'function' ? validator(value, allValues) : undefined), undefined);
11+
return validators.reduce(
12+
(error, validator) => error || (typeof validator === 'function' ? validator(value, allValues, meta) : undefined),
13+
undefined
14+
);
1215
};
1316

1417
export default composeValidators;

packages/react-form-renderer/src/files/validators.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { AnyObject } from './common';
33

44
export type DataTypeValidators = "string" | "integer" | "boolean" | "number" | "float";
55

6-
export type ValidatorFunction = (value: any, allValues?: object) => Promise<any> | ReactNode | undefined;
6+
export type ValidatorFunction = (value: any, allValues?: object, meta?: object) => Promise<any> | ReactNode | undefined;
77

88
export interface ValidatorConfiguration extends AnyObject {
99
type: string;
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import React from 'react';
2+
import { mount } from 'enzyme';
3+
4+
import FormRenderer from '../../files/form-renderer';
5+
import componentTypes from '../../files/component-types';
6+
import FormTemplate from '../../../../../__mocks__/mock-form-template';
7+
import useFieldApi from '../../files/use-field-api';
8+
import { act } from 'react-dom/test-utils';
9+
10+
describe('FormRenderer validator', () => {
11+
const TextField = (props) => {
12+
const { input, meta, ...rest } = useFieldApi(props);
13+
return (
14+
<div>
15+
<input {...input} {...rest} />
16+
{meta.error && <div id="error">{meta.error}</div>}
17+
</div>
18+
);
19+
};
20+
21+
it('pass value, allvalues, meta to custom validator func', async () => {
22+
expect.assertions(3);
23+
24+
const VALUE = 'some-value';
25+
const NAME = 'field1';
26+
const META = expect.any(Object);
27+
28+
const validator = (value, allValues, meta) => {
29+
if (value) {
30+
//skip initial validation
31+
expect(value).toEqual(VALUE);
32+
expect(allValues).toEqual({
33+
other: '111',
34+
[NAME]: VALUE
35+
});
36+
expect(meta).toEqual(META);
37+
}
38+
};
39+
40+
const wrapper = mount(
41+
<FormRenderer
42+
FormTemplate={(props) => <FormTemplate {...props} />}
43+
componentMapper={{
44+
[componentTypes.TEXT_FIELD]: TextField
45+
}}
46+
schema={{
47+
fields: [{ component: 'text-field', name: NAME, validate: [validator] }]
48+
}}
49+
onSubmit={jest.fn()}
50+
initialValues={{ other: '111' }}
51+
/>
52+
);
53+
54+
await act(async () => {
55+
wrapper.find('input').simulate('change', { target: { value: VALUE } });
56+
});
57+
});
58+
});

packages/react-form-renderer/src/validators/helpers.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { ValidatorFunction } from "../files/validators";
22
import { ReactNode } from "react";
3-
import { ValidatorType } from "../files/use-field-api";
43
import { MessageTypes } from "./messages";
54

65
// tslint:disable-next-line: ban-types

packages/react-form-renderer/src/validators/helpers.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ export const memoize = (func) => {
3030
func.cache = {};
3131
}
3232

33-
return (options) => {
34-
const key = stringify(options);
35-
return HAS_PROP.call(func.cache, key) ? func.cache[key] : (func.cache[key] = func(options));
33+
return (value, allValues, ...options) => {
34+
const key = stringify(value, allValues);
35+
return HAS_PROP.call(func.cache, key) ? func.cache[key] : (func.cache[key] = func(value, allValues, ...options));
3636
};
3737
};
3838

packages/react-renderer-demo/src/pages/renderer/validators.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ As validator you can provide your custom function:
3737

3838
<CodeExample mode="preview" source="components/validators/custom-function" />
3939

40-
The function takes `value` as an argument and should return undefined when pasess or string as an error message when fails.
40+
Please see [final form validate prop](https://final-form.org/docs/react-final-form/types/FieldProps#validate). This function takes `value`, `allValues` and `meta` as arguments and returns error message when it fails, otherwise it returns undefined.
4141

4242
## Async validator
4343

0 commit comments

Comments
 (0)