-
Notifications
You must be signed in to change notification settings - Fork 833
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve onError validation #1730
Changes from 26 commits
5563142
70b66d4
e9a0687
4f2207f
868358a
679ea8d
a501984
a1a6b42
5ca8ef2
3af9888
71981e0
cbe5fc4
3eddd8b
f21609c
754a95b
58f12c7
e349496
5bce1e4
e4166a7
860d6f5
c73d4e7
8dedc04
66eb022
af381ef
1201eef
79cea16
806b63c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,109 @@ | ||||||
import React from 'react'; | ||||||
import Grid from '@material-ui/core/Grid'; | ||||||
import TextField from '@material-ui/core/TextField'; | ||||||
import { Formik, Form, Field, FieldProps } from 'formik'; | ||||||
import { format, isWeekend, isWednesday } from 'date-fns'; | ||||||
import { DatePicker, DatePickerProps } from '@material-ui/pickers'; | ||||||
|
||||||
interface DatePickerFieldProps extends FieldProps, DatePickerProps { | ||||||
getShouldDisableDateError: (date: Date) => string; | ||||||
} | ||||||
|
||||||
const DatePickerField: React.FC<DatePickerFieldProps> = ({ | ||||||
form, | ||||||
field: { value, name }, | ||||||
maxDate = new Date('2100-01-01'), | ||||||
minDate = new Date('1900-01-01'), | ||||||
getShouldDisableDateError, | ||||||
...other | ||||||
}) => { | ||||||
const currentError = form.errors[name]; | ||||||
const toShowError = Boolean(currentError && form.touched[name]); | ||||||
|
||||||
return ( | ||||||
<DatePicker | ||||||
autoOk | ||||||
clearable | ||||||
minDate={minDate} | ||||||
maxDate={maxDate} | ||||||
value={value} | ||||||
onError={(reason, value) => { | ||||||
switch (reason) { | ||||||
case 'invalidDate': | ||||||
form.setFieldError(name, 'Invalid date format'); | ||||||
break; | ||||||
|
||||||
case 'disablePast': | ||||||
form.setFieldError(name, 'Values in the past are not allowed'); | ||||||
break; | ||||||
|
||||||
case 'maxDate': | ||||||
form.setFieldError(name, `Date should not be after ${format(maxDate, 'P')}`); | ||||||
break; | ||||||
|
||||||
case 'minDate': | ||||||
form.setFieldError(name, `Date should not be after ${format(maxDate, 'P')}`); | ||||||
break; | ||||||
|
||||||
case 'shouldDisableDate': | ||||||
// shouldDisableDate returned true, render custom message according to the `shouldDisableDate` logic | ||||||
form.setFieldError(name, getShouldDisableDateError(value)); | ||||||
break; | ||||||
|
||||||
default: | ||||||
form.setErrors({ | ||||||
...form.errors, | ||||||
[name]: undefined, | ||||||
}); | ||||||
} | ||||||
}} | ||||||
// Make sure that your 3d param is set to `true` on order to not clear errors | ||||||
onChange={date => form.setFieldValue(name, date, false)} | ||||||
renderInput={props => ( | ||||||
<TextField | ||||||
{...props} | ||||||
name={name} | ||||||
error={toShowError} | ||||||
helperText={toShowError ? currentError ?? props.helperText : undefined} | ||||||
// Make sure that your 3d param is set to `true` on order to not clear errors | ||||||
onBlur={() => form.setFieldTouched(name, true, false)} | ||||||
/> | ||||||
)} | ||||||
{...other} | ||||||
/> | ||||||
); | ||||||
}; | ||||||
|
||||||
const FormikExample = () => { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I prefer export default to be always the last export. It is more readable. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We systematically use the other way around to 1. increase the code density of the demos, 2. reduce the duplicate of the name of the demo. I think that it's important we still to a single convention. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, but for now pickers are standalone project. And if we are not planning to migrate docs before v5 we could stick to the our internal conventions for now. (before we merge docs) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that we can break down the dicussion in 3 different topics:
|
||||||
return ( | ||||||
<Formik onSubmit={console.log} initialValues={{ date: new Date() }}> | ||||||
dmtrKovalenko marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
{({ values, errors }) => ( | ||||||
<Form> | ||||||
<Grid container> | ||||||
<Grid item container justify="center" xs={12}> | ||||||
<Field | ||||||
name="date" | ||||||
disablePast | ||||||
component={DatePickerField} | ||||||
shouldDisableDate={(date: Date) => isWeekend(date) || isWednesday(date)} | ||||||
getShouldDisableDateError={(date: Date) => { | ||||||
return isWeekend(date) | ||||||
? 'Weekends are not allowed' | ||||||
: 'Wednesdays are not allowed'; | ||||||
}} | ||||||
/> | ||||||
</Grid> | ||||||
|
||||||
<Grid item xs={12} sm={12} style={{ margin: '24px' }}> | ||||||
<pre> | ||||||
<code>{JSON.stringify({ errors, values }, null, 2)}</code> | ||||||
</pre> | ||||||
</Grid> | ||||||
</Grid> | ||||||
</Form> | ||||||
)} | ||||||
</Formik> | ||||||
); | ||||||
}; | ||||||
|
||||||
export default FormikExample; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import React from 'react'; | ||
import { date, object } from 'yup'; | ||
import { Grid } from '@material-ui/core'; | ||
import { TextField } from '@material-ui/core'; | ||
import { Formik, Form, Field, FieldProps } from 'formik'; | ||
import { DatePicker, BaseDatePickerProps } from '@material-ui/pickers'; | ||
|
||
interface DatePickerFieldProps extends FieldProps, BaseDatePickerProps { | ||
getShouldDisableDateError: (date: Date) => string; | ||
} | ||
|
||
const DatePickerField: React.FC<DatePickerFieldProps> = ({ | ||
field, | ||
form, | ||
maxDate = new Date('2100-01-01'), | ||
minDate = new Date('1900-01-01'), | ||
getShouldDisableDateError, | ||
...other | ||
}) => { | ||
const currentError = form.errors[field.name]; | ||
|
||
return ( | ||
<DatePicker | ||
autoOk | ||
clearable | ||
minDate={minDate} | ||
maxDate={maxDate} | ||
value={field.value} | ||
onChange={date => form.setFieldValue(field.name, date, true)} | ||
renderInput={props => ( | ||
<TextField | ||
name={field.name} | ||
{...props} | ||
error={Boolean(currentError)} | ||
helperText={currentError ?? props.helperText} | ||
/> | ||
)} | ||
{...other} | ||
/> | ||
); | ||
}; | ||
|
||
const schema = object({ | ||
date: date() | ||
.required() | ||
.min(new Date()) | ||
.max(new Date('2100-10-10')), | ||
}); | ||
|
||
const FormikExample = () => { | ||
return ( | ||
<Formik validationSchema={schema} onSubmit={console.log} initialValues={{ date: new Date() }}> | ||
{({ values, errors }) => ( | ||
<Form> | ||
<Grid container> | ||
<Grid item container justify="center" xs={12}> | ||
<Field name="date" disablePast component={DatePickerField} /> | ||
</Grid> | ||
|
||
<Grid item xs={12} sm={12} style={{ margin: '24px' }}> | ||
<pre> | ||
<code>{JSON.stringify({ errors, values }, null, 2)}</code> | ||
</pre> | ||
</Grid> | ||
</Grid> | ||
</Form> | ||
)} | ||
</Formik> | ||
); | ||
}; | ||
|
||
export default FormikExample; |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For consistency
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean under consistency?
function
vsconst
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean that we systematically write private components following this pattern:
and for public ones: