Skip to content

Commit 251f88d

Browse files
authored
Merge pull request #360 from panichevoleg/feature/640794-form-validation
Updated `Form` component to have onValidate callback
2 parents 3d37742 + 4c7151b commit 251f88d

File tree

2 files changed

+39
-9
lines changed

2 files changed

+39
-9
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## 2.1.5
44

55
- Improved trigger and added CNAME to kitchen sink
6+
- Updated `Form` component to have `onValidate` callback
67

78
## 2.1.4
89

src/components/Form/index.tsx

+38-9
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@ export interface FormChangeEvent {
3030
changed: boolean;
3131
}
3232

33+
export interface FormValidateEvent {
34+
/**
35+
* The current values of the form fields.
36+
*/
37+
value: FormValuesData;
38+
/**
39+
* Validation errors
40+
*/
41+
errors?: Array<FormValidationError>;
42+
}
43+
3344
export interface FormValuesData {
3445
[name: string]: any;
3546
}
@@ -65,6 +76,10 @@ export interface FormProps<FormValues> extends StandardProps {
6576
* Event emitted when the form is submitted.
6677
*/
6778
onSubmit?(e: FormSubmitEvent): void;
79+
/**
80+
* Event emitted when form errors are set or cleared
81+
*/
82+
onValidate?(e: FormValidateEvent): void;
6883
/**
6984
* Disables the form in case of invalid input. Effectively
7085
* disables the possibility of submitting forms.
@@ -159,6 +174,26 @@ export class Form<Values extends FormValuesData> extends React.Component<FormPro
159174
}
160175
}
161176

177+
componentDidUpdate(_: FormProps<Values>, prevState: FormState<Values>) {
178+
const { onValidate } = this.props;
179+
const { errors, current } = this.state;
180+
181+
if (typeof onValidate === 'function' && JSON.stringify(prevState.errors) !== JSON.stringify(errors)) {
182+
const arrayErrors = this.getErrorsAsArray(errors);
183+
onValidate({ errors: arrayErrors, value: current });
184+
}
185+
}
186+
187+
private getErrorsAsArray(errors: FormState<Values>['errors']) {
188+
return Object.keys(errors).reduce<Array<FormValidationError>>((arrayErrors, field) => {
189+
const error = errors[field];
190+
if (error) {
191+
arrayErrors.push({ field, error });
192+
}
193+
return arrayErrors;
194+
}, []);
195+
}
196+
162197
private setValues(current: Values, changed: boolean) {
163198
const keys = Object.keys(current);
164199

@@ -248,7 +283,7 @@ export class Form<Values extends FormValuesData> extends React.Component<FormPro
248283
if (name) {
249284
this.fields.push(field);
250285

251-
let error;
286+
let error: React.ReactChild | undefined;
252287
if (name in current) {
253288
const value = current[name];
254289
error = this.getError(name, value);
@@ -262,7 +297,7 @@ export class Form<Values extends FormValuesData> extends React.Component<FormPro
262297
}
263298

264299
if (error) {
265-
this.setState({ errors: { ...errors, [name]: error } as FormState<Values>['errors'] });
300+
this.setState(({ errors }) => ({ errors: { ...errors, [name]: error } }));
266301
}
267302
}
268303
},
@@ -280,13 +315,7 @@ export class Form<Values extends FormValuesData> extends React.Component<FormPro
280315
this.setErrors(current);
281316

282317
if (!disabled && typeof onSubmit === 'function') {
283-
const arrayErrors = Object.keys(errors).reduce<Array<FormValidationError>>((arrayErrors, field) => {
284-
const error = errors[field];
285-
if (error) {
286-
arrayErrors.push({ field, error });
287-
}
288-
return arrayErrors;
289-
}, []);
318+
const arrayErrors = this.getErrorsAsArray(errors);
290319

291320
this.setState(
292321
{

0 commit comments

Comments
 (0)