Skip to content

Commit a65bdae

Browse files
committed
Rewritten doubterPlugin README.md
1 parent 3be5350 commit a65bdae

File tree

3 files changed

+155
-62
lines changed

3 files changed

+155
-62
lines changed

README.md

+13-61
Original file line numberDiff line numberDiff line change
@@ -462,12 +462,12 @@ you can use `form` tags as you did before, but read input values from the `Field
462462

463463
```tsx
464464
const App = () => {
465-
const rootField = useField({ foo: 'bar' });
465+
const rootField = useField({ bar: 'foo' });
466466

467467
const handleSubmit = (event: SyntheticEvent): void => {
468468
event.preventDefault();
469469

470-
// Acquire the current value of the root field
470+
// The form value to submit
471471
const value = rootField.getValue();
472472
};
473473

@@ -498,78 +498,30 @@ You can always [create a plugin](#plugins) that would enhance the `Field` with c
498498

499499
# Validation
500500

501-
Roqueform isn't tied to any validation library. You can use an existing plugin, or write your own plugin to extend
502-
Roqueform with validation provided by an arbitrary library.
501+
Roqueform isn't tied to any validation library. You can use an existing plugin, or write your own to extend Roqueform
502+
with validation provided by an arbitrary library.
503503

504-
For example, let's consider a [@roqueform/doubter-plugin](./packages/doubter-plugin) that enables a no-hassle validation
505-
using [Doubter](https://github.com/smikhalevski/doubter).
504+
Currently, the only available validation plugin [@roqueform/doubter-plugin](./packages/doubter-plugin) which enables
505+
uses [Doubter](https://github.com/smikhalevski/doubter) under-the-hood.
506506

507507
```ts
508-
import { useErrors, useField } from 'roqueform';
508+
import { useField } from 'roqueform';
509509
import { doubterPlugin } from '@roqueform/doubter-plugin';
510510
import * as d from 'doubter';
511511

512-
const fieldType = d.object({
512+
const valueType = d.object({
513513
bar: d.string().min(5)
514514
});
515515

516-
const field = useField({ bar: 'qux' }, doubterPlugin(fieldType));
517-
```
518-
519-
The `field` value type is inferred from the `fieldType`.
516+
const rootField = useField({ bar: 'qux' }, doubterPlugin(valueType));
520517

521-
Plugin enhances all fields with `validate` method that triggers the validation:
518+
rootField.validate();
522519

523-
```ts
524-
field.validate();
525-
526-
field.at('bar').getIssue()?.message
527-
// → 'Must have the minimum length of 5'
520+
rootField.at('bar').getIssue();
521+
// → { message: 'Must have the minimum length of 5', … }
528522
```
529523

530-
You can manually set and clear field errors:
531-
532-
```ts
533-
field.at('bar').setIssue({ message: 'Oh, snap!' });
534-
535-
field.at('bar').clearIssue();
536-
```
537-
538-
This comes in handy when you receive an error after a backend validation and want to associate it with a particular
539-
field.
540-
541-
```tsx
542-
const handleSubmit = (event: SyntheticEvent) => {
543-
field.validate();
544-
545-
if (field.isInvalid()) {
546-
event.preventDefault();
547-
}
548-
};
549-
550-
<form onSubmit={handleSubmit}>
551-
<Field field={field.at('bar')}>
552-
{barField => (
553-
<>
554-
<input
555-
name="bar"
556-
value={barField.getValue()}
557-
onChange={event => {
558-
barField.dispatchValue(event.target.value);
559-
}}
560-
aria-invalid={barField.isInvalid()}
561-
/>
562-
563-
{barField.getIssue()?.message}
564-
</>
565-
)}
566-
</Field>
567-
568-
<button type="submit">
569-
{'Submit'}
570-
</button>
571-
</form>
572-
```
524+
[Plugin usage details can be found here.](./packages/doubter-plugin)
573525

574526
# Accessors
575527

packages/doubter-plugin/README.md

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# Doubter plugin for Roqueform
2+
3+
Plugin that enhances [Roqueform](https://github.com/smikhalevski/roqueform) fields with validation methods powered by
4+
[Doubter](https://github.com/smikhalevski/doubter).
5+
6+
```sh
7+
npm install --save-prod @roqueform/doubter-plugin
8+
```
9+
10+
# Usage example
11+
12+
🔥&ensp;[**Try it on CodeSandbox**](https://codesandbox.io/s/roqueform-doubter-plugin-example-74hkgw)
13+
14+
```tsx
15+
import * as d from 'doubter';
16+
import { useField } from 'roqueform';
17+
import { doubterPlugin } from '@roqueform/doubter-plugin';
18+
19+
const valueType = d.object({
20+
bar: d.string().min(1),
21+
});
22+
23+
export const App = () => {
24+
const rootField = useField({ bar: '' }, doubterPlugin(valueType));
25+
26+
const handleSubmit = (event: SyntheticEvent): void => {
27+
event.preventDefault();
28+
29+
// Trigger validation
30+
rootField.validate();
31+
32+
if (rootField.isInvalid()) {
33+
// Isses are associated with fields automatically
34+
return;
35+
}
36+
37+
// The form value to submit
38+
const value = rootField.getValue();
39+
};
40+
41+
return (
42+
<form onSubmit={handleSubmit}>
43+
44+
<Field field={rootField.at('bar')}>
45+
{barField => (
46+
<>
47+
<input
48+
value={barField.getValue()}
49+
onChange={event => {
50+
barField.dispatchValue(event.target.value);
51+
}}
52+
aria-invalid={barField.isInvalid()}
53+
/>
54+
55+
{barField.getIssue()?.message}
56+
</>
57+
)}
58+
</Field>
59+
60+
<button type="submit">
61+
{'Submit'}
62+
</button>
63+
64+
</form>
65+
);
66+
};
67+
```
68+
69+
# Validating fields
70+
71+
First, you should first define your runtime data types using [Doubter](https://github.com/smikhalevski/doubter) DSL
72+
methods.
73+
74+
```ts
75+
import * as d from 'doubter';
76+
77+
const valueType = d.object({
78+
bar: d.string().min(5)
79+
});
80+
// → Type<{ bar: string }>
81+
```
82+
83+
Then you can create a new field and enhance it with validation methods:
84+
85+
```ts
86+
import { useField } from 'roqueform';
87+
import { doubterPlugin } from '@roqueform/doubter-plugin';
88+
89+
const rootField = useField({ bar: 'qux' }, doubterPlugin(valueType));
90+
```
91+
92+
Type of the field value is inferred from the provided runtime type definition, so everything remains statically checked
93+
even there's no TypeScript types were explicitly specified.
94+
95+
When you call the `validate` method it triggers validation of the field and all of its derived fields. So if you call
96+
`validate` on the derived field, it won't validate the parent field:
97+
98+
```ts
99+
// rootField is not validated here!
100+
rootField.at('bar').validate();
101+
```
102+
103+
So it's safe to trigger validation of a single text field on every keystroke, since it does't have an overhead of
104+
validating the whole form object. On the other hand, you can validate the whole form by calling validate on the root
105+
field.
106+
107+
To detect whether the field, or any of its derived fields contain an issue:
108+
109+
```ts
110+
rootField.isInvalid();
111+
// → true
112+
```
113+
114+
To retrieve an issue associated with a particular field:
115+
116+
```ts
117+
rootField.at('bar').getIssue();
118+
// → { message: 'Must have the minimum length of 5', … }
119+
```
120+
121+
# Manage issues manually
122+
123+
You can manually associate an issue with the field:
124+
125+
```ts
126+
rootField.at('bar').setIssue({ message: 'Oh, snap!' });
127+
```
128+
129+
This allows you to mix client-side and server-side validation using the same mechanism.
130+
131+
To delete an issue for the particular field:
132+
133+
```ts
134+
rootField.at('bar').deleteIssue();
135+
```
136+
137+
Sometimes it is required to clear issues of the field itself and all of its derived fields:
138+
139+
```ts
140+
rootField.clearIssues();
141+
```

packages/doubter-plugin/src/test/doubterPlugin.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as d from 'doubter';
22
import { doubterPlugin } from '../main';
3-
import { createField, objectAccessor } from 'roqueform/src/main';
3+
import { createField, objectAccessor } from 'roqueform';
44

55
describe('doubterPlugin', () => {
66
const fooType = d.object({

0 commit comments

Comments
 (0)