Skip to content

Commit

Permalink
Improve onError validation (#1730)
Browse files Browse the repository at this point in the history
* Introduce reason-based validation

* Remove dead validation code

* Implement new validation for TimePicker and DateTimePicker

* Remove redux form docs example

* Add Formik with validation schema example

* More tests

* TimePicker validation tests

* Move parsing min/max date up to the root component

* Use touched state in the formik example

* Remove console.logs

* Fix lint and build errors

* Remove visual regression flakiness with time validation

* Remove emptyInputText

* Fix validation tests

* Commit .size-snapshot

* Implement validation for DateRangePicker.tsx

* Add DateRange validation tests

* Fix linter

* Fix broken design of date rangepicker input parsing

* Remove <Code> from formik examples

* Update yarn.lock

* Update docs/pages/guides/FormikOurValidation.example.tsx

Co-authored-by: Olivier Tassinari <olivier.tassinari@gmail.com>

* Update docs/pages/guides/FormikOurValidation.example.tsx

Co-authored-by: Olivier Tassinari <olivier.tassinari@gmail.com>

* Update docs/pages/guides/FormikOurValidation.example.tsx

Co-authored-by: Olivier Tassinari <olivier.tassinari@gmail.com>

* Update new forms example to be more consolidated with @materail-ui/core

Co-authored-by: Olivier Tassinari <olivier.tassinari@gmail.com>
  • Loading branch information
dmtrKovalenko and oliviertassinari committed May 6, 2020
1 parent 3d16fc3 commit bffad8f
Show file tree
Hide file tree
Showing 45 changed files with 1,230 additions and 1,279 deletions.
2 changes: 1 addition & 1 deletion docs/layout/components/navigationMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const navItems = [
title: 'Guides',
children: [
{ title: 'Accessibility', href: '/guides/accessibility' },
{ title: 'Form integration', href: '/guides/form-integration' },
{ title: 'Form integration', href: '/guides/forms' },
{ title: 'CSS overrides', href: '/guides/css-overrides' },
{ title: 'Passing date adapter', href: '/guides/date-adapter-passing' },
{ title: 'Date management customization', href: '/guides/date-io-customization' },
Expand Down
8 changes: 3 additions & 5 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"@types/prismjs": "^1.9.1",
"@types/react": "^16.8.13",
"@types/react-kawaii": "^0.11.0",
"@types/react-redux": "^7.1.7",
"@types/sinon": "^7.0.13",
"@types/yup": "^0.28.0",
"@zeit/next-bundle-analyzer": "^0.1.2",
"@zeit/next-css": "^1.0.1",
"@zeit/next-mdx": "^1.2.0",
Expand Down Expand Up @@ -65,15 +65,13 @@
"react-jss": "^8.6.1",
"react-kawaii": "^0.16.0",
"react-markdown": "^4.2.2",
"react-redux": "^7.2.0",
"redux": "^4.0.5",
"redux-form": "^8.3.0",
"remark-slug": "^6.0.0",
"safe-json-stringify": "^1.2.0",
"sinon": "^9.0.2",
"styled-jsx": "^3.2.5",
"ts-loader": "^6.0.2",
"typescript": "^3.8.3"
"typescript": "^3.8.3",
"yup": "^0.28.5"
},
"devDependencies": {
"dotenv": "^8.2.0",
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/demo/timepicker/TimeValidation.example.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { TextField } from '@material-ui/core';
import { TimePicker } from '@material-ui/pickers';

function TimeValidation() {
const [selectedDate, handleDateChange] = useState(new Date());
const [selectedDate, handleDateChange] = useState(new Date('2020-01-01 12:00'));

return (
<Fragment>
Expand Down
57 changes: 0 additions & 57 deletions docs/pages/guides/Formik.example.jsx

This file was deleted.

115 changes: 115 additions & 0 deletions docs/pages/guides/FormikOurValidation.example.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
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;
}

function DatePickerField({
form,
field: { value, name },
maxDate = new Date('2100-01-01'),
minDate = new Date('1900-01-01'),
getShouldDisableDateError,
...other
}: DatePickerFieldProps) {
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 `false` 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 `false` on order to not clear errors
onBlur={() => form.setFieldTouched(name, true, false)}
/>
)}
{...other}
/>
);
}

function validateDatePickerValue(date: Date) {
if (isWeekend(date)) {
return 'Weekends are not allowed';
}

if (isWednesday(date)) {
return 'Wednesdays are not allowed';
}

return null;
}

export default function FormikExample() {
return (
<Formik 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}
shouldDisableDate={(date: Date) => validateDatePickerValue(date) !== null}
getShouldDisableDateError={validateDatePickerValue}
/>
</Grid>

<Grid item xs={12} sm={12} style={{ margin: '24px' }}>
<pre>
<code>{JSON.stringify({ errors, values }, null, 2)}</code>
</pre>
</Grid>
</Grid>
</Form>
)}
</Formik>
);
}
73 changes: 73 additions & 0 deletions docs/pages/guides/FormikValidationSchema.example.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
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;
}

function DatePickerField({
field,
form,
maxDate = new Date('2100-01-01'),
minDate = new Date('1900-01-01'),
getShouldDisableDateError,
...other
}: DatePickerFieldProps) {
const currentError = form.errors[field.name];

return (
<DatePicker
autoOk
clearable
minDate={minDate}
maxDate={maxDate}
value={field.value}
// Make sure that your 3d param is set to `true` in order to run validation
onChange={date => form.setFieldValue(field.name, date, true)}
renderInput={props => (
<TextField
name={field.name}
{...props}
error={Boolean(currentError)}
helperText={currentError ?? props.helperText}
// Make sure that your 3d param is set to `true` in order to run validation
onBlur={() => form.setFieldTouched(name, true, true)}
/>
)}
{...other}
/>
);
}

const schema = object({
date: date()
.required()
.min(new Date())
.max(new Date('2100-10-10')),
});

export default function FormikValidationSchemaExample() {
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>
);
}
90 changes: 0 additions & 90 deletions docs/pages/guides/ReduxForm.example.jsx

This file was deleted.

1 comment on commit bffad8f

@vercel
Copy link

@vercel vercel bot commented on bffad8f May 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.