React Final Form + React DatePicker Implementation with Validations

A working example can be found at Codesandbox

React Final Form is a popular Reactjs Plugin for handling forms. On the other hand React DatePicker is another popular ReactJs plugin with almost 5.6M downloads per week.

React Final Form’s form validation works out of the box, for normal fields. However to handle form validation for third party components can be tricky In this example I am going to share an example of React DatePicker field inside React Final Form component where it is validated as a normal React Final Form field.

I will share only the code here. A working example can be found at this Codesandbox

Here starts the code.

import React, { useState } from "react";
import "./styles.css";
import { Form, Field } from "react-final-form";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import { parse, format, isValid, toDate } from "date-fns";
import { enUS } from "date-fns/locale";

const Error = ({ name }) => (
  <Field
    name={name}
    subscribe={{ touched: true, error: true }}
    render={({ meta: { touched, error } }) =>
      touched && error ? <span className="error">{error}</span> : null
    }
  />
);

const RenderDatePicker = ({ name, input, input: { value, onChange } }) => {
  let isValidDate = false;
  let selected = null;

  if (value) {
    const parsedDate = parse(value, "P", new Date(), { locale: enUS });
    isValidDate = isValid(parsedDate);
    selected = isValidDate ? toDate(parsedDate) : null;
  }
  return (
    <DatePicker
      placeholderText={
        value ? format(new Date(value), "MM/dd/yyyy") : "Enter date"
      }
      dateFormat="MM/dd/yyyy"
      selected={selected} // needs to be checked if it is valid date
      disabledKeyboardNavigation
      name={name}
      onChange={(date) => {
        // On Change, you should use final-form Field Input prop to change the value
        if (isValid(date)) {
          input.onChange(format(new Date(date), "MM/dd/yyyy"));
        } else {
          input.onChange(null);
        }
      }}
    />
  );
};

const required = (value) => (value ? undefined : "Date is required");

export default function App() {
  const [initialValues] = useState({ start_date: new Date() });

  const onSubmit = (values) => {
    console.log(values);
  };

  const validate = (values) => {
    let errors = {};
    if (!values.name) {
      errors.name = "Name is required";
    }
    return errors;
  };

  return (
    <div className="App">
      <h1>React Final Form + React DatePicker</h1>
      <h2>An Working example of React Final form with read</h2>
      <Form
        onSubmit={onSubmit}
        validate={validate}
        initialValues={initialValues}
      >
        {({ handleSubmit, form, submitting, pristine, values }) => (
          <form className="form" onSubmit={handleSubmit}>
            <Field name="name">
              {({ input, meta }) => (
                <div className="form__form-group">
                  <span className="form__form-group-label">Name</span>
                  <div className="form__form-group-field">
                    <div className="form__form-group-row">
                      <input
                        type="text"
                        {...input}
                        placeholder="Enter your name"
                      />
                      {meta.touched && meta.error && (
                        <span className="error">{meta.error}</span>
                      )}
                    </div>
                  </div>
                </div>
              )}
            </Field>
            <div className="form__form-group">
              <span className="form__form-group-label">Date</span>
              <div className="form__form-group-field">
                <div className="form__form-group-row">
                  <Field
                    name="start_date"
                    component={RenderDatePicker}
                    validate={required}
                  />
                  <Error name="start_date" />
                </div>
              </div>
            </div>
            <button
              type="submit"
              disabled={submitting}
              className="btn btn-primary btn-sm"
              color="#ffffff"
            >
              Submit
            </button>
          </form>
        )}
      </Form>
    </div>
  );
}

 

Leave a Reply