Skip to content

Commit 0c6e78e

Browse files
committed
Add standalone validation to documentation
1 parent 21d12f2 commit 0c6e78e

File tree

4 files changed

+198
-0
lines changed

4 files changed

+198
-0
lines changed

packages/react-renderer-demo/src/components/navigation/schemas/schema.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import schemaHooks from './hooks.schema';
55
import mappersSchema from './mappers.schema';
66
import customExamplesSchema from './custom-examples.schema';
77
import providedMappersSchema from './provider-mappers.schema';
8+
import utilitiesSchema from './utilities.schema';
89

910
const schema = [
1011
{
@@ -45,6 +46,12 @@ const schema = [
4546
noRoute: true,
4647
fields: providedMappersSchema
4748
},
49+
{
50+
title: 'Utilities',
51+
link: 'utilities',
52+
noRoute: true,
53+
fields: utilitiesSchema
54+
},
4855
{
4956
title: 'Examples',
5057
link: 'examples',
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
const customExamplesSchema = [
2+
{
3+
component: 'standalone-validation',
4+
linkText: 'Standalone validation'
5+
}
6+
];
7+
8+
export default customExamplesSchema;
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import validation from '@data-driven-forms/react-form-renderer/validation';
2+
import React, { useEffect, useState } from 'react';
3+
4+
const asyncValidate = (pass) => {
5+
const method = pass ? 'resolve' : 'reject';
6+
7+
return Promise[method]().catch(() => {
8+
// eslint-disable-next-line no-throw-literal
9+
throw 'some async validation error';
10+
});
11+
};
12+
13+
const schema = {
14+
fields: [
15+
{ name: 'no-validation', component: 'checkbox' },
16+
{ name: 'pass', component: 'select', validate: [{ type: 'required' }] },
17+
{ name: 'invisible', component: 'dual-list', condition: { when: 'x', is: 'abc' }, validate: [{ type: 'required' }] },
18+
{ name: 'fail', component: 'select', validate: [{ type: 'required' }] },
19+
{ name: 'subform', component: 'subform', fields: [{ name: 'fail-in-nest', component: 'select', validate: [{ type: 'required' }] }] },
20+
{ name: 'fail.nested', component: 'select', validate: [{ type: 'required' }] },
21+
{ name: 'passes.nested', component: 'select', validate: [{ type: 'required' }] },
22+
{ name: 'fail-function', component: 'select', validate: [() => 'error-message-from-function'] },
23+
{ name: 'fail-custom', component: 'select', validate: [{ type: 'custom' }] },
24+
{ name: 'async-fail', component: 'select', validate: [asyncValidate] },
25+
{ name: 'async-pass', component: 'select', validate: [asyncValidate] },
26+
{ name: 'datatype-fail', component: 'select', dataType: 'number' },
27+
{ name: 'fail-multiple', component: 'select', validate: [{ type: 'required' }, { type: 'pattern', pattern: /abc/ }] },
28+
{ name: 'double-fail', component: 'select', validate: [{ type: 'required' }] },
29+
{ name: 'double-fail', component: 'select', validate: [{ type: 'pattern', pattern: /abc/ }] },
30+
{ name: 'double-fail-1', component: 'select', validate: [{ type: 'required' }] },
31+
{ name: 'double-fail-1', component: 'select', validate: [{ type: 'pattern', pattern: /abc/ }] },
32+
{ name: 'double-fail-2', component: 'select', validate: [{ type: 'required' }] },
33+
{ name: 'double-fail-2', component: 'select', dataType: 'number' },
34+
{ name: 'combined-fail', component: 'select', dataType: 'number', validate: [{ type: 'required' }] },
35+
{ name: 'combined-fail-1', component: 'select', dataType: 'number', validate: [{ type: 'required' }] },
36+
{ name: 'combined-pass', component: 'select', dataType: 'number', validate: [{ type: 'required' }] }
37+
]
38+
};
39+
40+
const options = {
41+
values: {
42+
pass: 'some-value',
43+
'async-pass': 'some-value',
44+
passes: { nested: 'some-value' },
45+
'datatype-fail': 'abc',
46+
'fail-multiple': 'ccc',
47+
'double-fail': 'ccc',
48+
'double-fail-2': 'ccc',
49+
'combined-fail-1': 'string',
50+
'combined-pass': 123
51+
},
52+
validatorMapper: {
53+
custom: () => () => 'custom error validator'
54+
}
55+
};
56+
57+
const StandaloneValidation = () => {
58+
const [errors, setErrors] = useState();
59+
60+
useEffect(() => {
61+
(async () => {
62+
const formErrors = await validation(schema, options);
63+
64+
setErrors(formErrors);
65+
})();
66+
}, []);
67+
68+
if (!errors) {
69+
return 'Validating...';
70+
}
71+
72+
return (
73+
<React.Fragment>
74+
<h1>Schema</h1>
75+
<pre>Check code example</pre>
76+
<h1>Options</h1>
77+
<pre>Check code example</pre>
78+
<h1>Errors</h1>
79+
<pre>{JSON.stringify(errors, null, 2)}</pre>
80+
</React.Fragment>
81+
);
82+
};
83+
84+
export default StandaloneValidation;
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import DocPage from '@docs/doc-page';
2+
import CodeExample from '@docs/code-example';
3+
4+
<DocPage>
5+
6+
# Standalone validation
7+
8+
*@data-driven-forms/react-form-renderer/validation*
9+
10+
*(schema: Schema, options: Options) => object: Errors*
11+
12+
Data Driven Forms provides an async function that validates values based on a provided schema. This feature can be useful to implement validation on backend endpoints with using the same schema as in frontend applications.
13+
14+
## Schema
15+
16+
*object*
17+
18+
The same [schema](/schema/introduction) as for the form renderer. Validation supports all features except array validators that are being used by field arrays. This functionallity will be implemented in the future.
19+
20+
## Options
21+
22+
*object*
23+
24+
```ts
25+
{
26+
values: AnyObject;
27+
componentMapper?: ComponentMapper;
28+
validatorMapper?: ValidatorMapper;
29+
actionMapper?: ActionMapper;
30+
schemaValidatorMapper?: SchemaValidatorMapper;
31+
omitWarnings?: boolean;
32+
}
33+
```
34+
35+
### Values
36+
37+
*object*
38+
39+
Form values as sent from the renderer.
40+
41+
---
42+
43+
### componentMapper
44+
45+
*object*
46+
47+
If not provided, all components are valid. [Read more](/components/renderer#componentmapper).
48+
49+
---
50+
51+
### validatorMapper
52+
53+
[Read more](/mappers/validator-mapper).
54+
55+
---
56+
57+
### actionMapper
58+
59+
[Read more](/mappers/action-mapper).
60+
61+
---
62+
63+
### schemaValidatorMapper
64+
65+
[Read more](/mappers/schema-validator-mapper).
66+
67+
---
68+
69+
### omitWarnings
70+
71+
*boolean*
72+
73+
If this attribute set to true, warnings will be ignored and won't appear in the errors object.
74+
75+
---
76+
77+
## Errors
78+
79+
*object*
80+
81+
A flat structure of errors.
82+
83+
```jsx
84+
{
85+
field: 'This field is required',
86+
'field-with-warning': { type: 'warning', error: 'This is warning' },
87+
'nested.field': 'Some error message'
88+
}
89+
```
90+
91+
## Schemas changed according to meta
92+
93+
If your form is changing according to form state or field states, be aware that this function will miss all meta information.
94+
95+
## Examples
96+
97+
<CodeExample source="components/utilities/standalone-validation" mode="preview" />
98+
99+
</DocPage>

0 commit comments

Comments
 (0)