Skip to content

Commit e05d3c8

Browse files
committed
update README.md
1 parent 0a51399 commit e05d3c8

1 file changed

Lines changed: 70 additions & 98 deletions

File tree

README.md

Lines changed: 70 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -10,48 +10,7 @@ Easy-to-use React hook for validating forms with the [class-validator](https://g
1010
npm install --save react-class-validator
1111
```
1212

13-
```typescript jsx
14-
15-
const validatorOptions: ValidatorContextOptions = {
16-
onErrorMessage: (error): string => {
17-
// custom error message handling (localization, etc)
18-
},
19-
resultType: 'boolean' // default, can also be set to 'map'
20-
}
21-
22-
render((
23-
<ValidatorProvider options={validatorOptions}>
24-
<MyComponent />
25-
</ValidatorProvider>
26-
), document.getElementById('root'))
27-
```
28-
29-
## Default onErrorMessage behavior
30-
The default behavior is to flatten all error constraints for each attribute.
31-
```typescript
32-
const getDefaultContextOptions = (): ValidatorContextOptions => ({
33-
onErrorMessage: (error) => Object.keys(error.constraints).map((key) => error.constraints[key])
34-
});
35-
```
36-
37-
### react-intl
38-
When using libraries such as [react-intl](https://github.com/formatjs/formatjs), you don't have to modify the existing
39-
`onErrorMessage` handler. Decorators are handled at source load, so you only need to include the `intl.formatMessage` in your message definition.
40-
41-
```typescript
42-
class Person {
43-
44-
@IsEmail({}, {
45-
message: intl.formatMessage(defineMessage({defaultMessage: 'Invalid email'}))
46-
})
47-
@IsNotEmpty({
48-
message: intl.formatMessage(defineMessage({defaultMessage: 'Email cannot be empty'}))
49-
})
50-
public email: string;
51-
52-
}
53-
54-
```
13+
Peer dependencies: `react >= 17.0.0`
5514

5615
## Usage
5716

@@ -63,106 +22,119 @@ import { IsNotEmpty } from "class-validator";
6322
class LoginValidation {
6423

6524
@IsNotEmpty({
66-
message: 'username cannot be empty'
25+
message: 'Username cannot be empty'
6726
})
6827
public username: string;
6928

7029
@IsNotEmpty({
71-
message: 'password cannot be empty'
30+
message: 'Password cannot be empty'
7231
})
7332
public password: string;
7433

7534
}
7635
```
7736

78-
Set up your form component to validate using your validation class.
37+
Use the `useValidation` hook in your component.
7938

80-
```typescript jsx
81-
const MyComponent = () => {
39+
```tsx
40+
import { useValidation } from "react-class-validator";
41+
42+
const LoginForm = () => {
8243

8344
const [username, setUsername] = useState('');
8445
const [password, setPassword] = useState('');
8546

86-
const [validate, errors] = useValidation(LoginValidation);
47+
const { validate, errors } = useValidation(LoginValidation);
8748

8849
return (
8950
<form onSubmit={async (evt) => {
90-
9151
evt.preventDefault();
92-
93-
// `validate` will return true if the submission is valid
94-
if (await validate({username, password})) {
95-
// ... handle valid submission
52+
if (!(await validate({ username, password }))) {
53+
// no validation errors — handle valid submission
9654
}
97-
9855
}}>
9956

100-
{/* use a filter so that the onBlur function will only validate username */}
101-
<input value={username} onChange={({target: {value}}) => setUsername(value)}
102-
onBlur={() => validate({username}, ['username'])}/>
103-
104-
{/* show error */}
105-
{errors.username && (
106-
<div className="error">
107-
{errors.username.map((message) => <strong>message</strong>)}
108-
</div>
109-
)}
57+
<input
58+
value={username}
59+
onChange={({ target: { value } }) => setUsername(value)}
60+
onBlur={() => validate({ username }, ['username'])}
61+
/>
62+
{errors?.username && errors.username.map((message, i) => (
63+
<strong key={i}>{message}</strong>
64+
))}
65+
66+
<input
67+
type="password"
68+
value={password}
69+
onChange={({ target: { value } }) => setPassword(value)}
70+
onBlur={() => validate({ password }, ['password'])}
71+
/>
72+
{errors?.password && errors.password.map((message, i) => (
73+
<strong key={i}>{message}</strong>
74+
))}
75+
76+
<button type="submit">Login</button>
11077

11178
</form>
11279
);
11380

11481
};
11582
```
11683

117-
## Usage With Formik
84+
## API
11885

119-
`react-class-validator` easily integrates with [Formik](https://formik.org/). You can simply use the `validate`
120-
function returned from `useValidation`, so long as the Formik fields are named the same as the keys in your validation
121-
class. Individual fields will have to be validated with `onBlur` functionality.
86+
### `useValidation(validationClass)`
12287

123-
### Formik error messages
88+
Returns an object with:
12489

125-
To display error messages without custom handling, messages will need to be outputted as a map upon validation.
126-
Do this by overriding the default `resultType` (you can also do this at the component-level).
90+
| Property | Type | Description |
91+
|------------|------|-------------|
92+
| `validate` | `(payload, filter?) => Promise<errors \| undefined>` | Validates the payload against the class. Returns `undefined` when valid. |
93+
| `errors` | `{ [key]: string[] } \| undefined` | Current validation errors keyed by property name. Each value is an array of error messages. |
12794

128-
```typescript
129-
const options: ValidatorContextOptions = {
130-
resultType: 'map'
131-
};
132-
```
95+
**Parameters:**
96+
97+
- `payload` — an object with the fields to validate (keys should match the validation class properties)
98+
- `filter` (optional) — an array of property names to exclude from the error result, useful for single-field validation on blur
99+
100+
## Usage with Formik
101+
102+
The `validate` function can be passed directly to Formik's `validate` prop. Since it returns an error map keyed by property name (or `undefined` when valid), it integrates seamlessly.
133103

134-
Then you can simply integrate with the default Formik flow.
104+
```tsx
105+
import { useValidation } from "react-class-validator";
106+
import { Field, Form, Formik } from "formik";
135107

136-
```typescript jsx
137-
export const Login: FunctionComponent = () => {
108+
const LoginForm = () => {
138109

139-
const [validate] = useValidation(LoginValidation);
110+
const { validate } = useValidation(LoginValidation);
140111

141112
return (
142-
<Formik initialValues={{username: '', password: ''}}
143-
validateOnBlur
144-
validateOnChange
145-
validate={validate}>
146-
{({values, touched, errors, handleChange, handleBlur}) => (
113+
<Formik
114+
initialValues={{ username: '', password: '' }}
115+
validate={validate}
116+
onSubmit={(values) => {
117+
// handle valid submission
118+
}}
119+
>
120+
{({ errors, touched }) => (
147121
<Form>
148-
149-
<label htmlFor="username">Username</label>
150-
<Field id="username" name="username" placeholder="Username" />
151-
152-
{errors.username && touched.username ? (
122+
<Field name="username" placeholder="Username" />
123+
{errors.username && touched.username && (
153124
<div>{errors.username}</div>
154-
) : null}
155-
156-
{/* other fields */}
157-
158-
<button type="submit">
159-
Submit
160-
</button>
161-
125+
)}
126+
127+
<Field name="password" type="password" placeholder="Password" />
128+
{errors.password && touched.password && (
129+
<div>{errors.password}</div>
130+
)}
131+
132+
<button type="submit">Submit</button>
162133
</Form>
163134
)}
164135
</Formik>
165136
);
137+
166138
};
167139
```
168140

0 commit comments

Comments
 (0)