reactjsreact-bootstrapformikreact-datetime

react-datetime formik validation


I'm using react-datetime compenent in my react-bootstrap form. Formik with Yup is used for validation.

import React from 'react';
import { Container, Form, Button, Alert, Row, Col, InputGroup } from "react-bootstrap";

import "react-datetime/css/react-datetime.css";

import { Formik} from 'formik';
import * as Icon from 'react-bootstrap-icons';
import * as yup from "yup"
import Datetime from 'react-datetime';
import moment from 'moment';

const validDOB = function( current ){
    return current.isBefore(moment());
};

const schema = yup.object().shape({
    userId: yup.string().required('Please enter a valid User ID'),
    userName: yup.string().required('User\'s Name cannot be empty'),
    userDOB: yup.string().required('User\'s Date of Birth cannot be empty'),
});

function AddWorkload(){
    return (
        <>
        <Container>
            <Row className="justify-content-md-center">
                <h3 style={{textAlign: 'center'}}>Add a New Workload</h3>
                <Formik
                    validationSchema={schema}
                    onSubmit={console.log}
                    initialValues={{
                        userId: '',
                        userName: '',
                        userDOB: '',
                    }}
                >
                {({
                    handleSubmit,
                    handleChange,
                    handleBlur,
                    values,
                    touched,
                    isValid,
                    errors,
                    setFieldValue,
                }) => (
                    <Col md lg="6">
                        <Form noValidate onSubmit={handleSubmit}>
                            <Form.Group controlId="userIdInput">
                                <Form.Label>User ID</Form.Label>
                                <InputGroup>
                                    <Form.Control 
                                        placeholder="User ID"
                                        type="text" 
                                        name="userId"
                                        value={values.userId}
                                        onChange={handleChange}
                                        isInvalid={!!errors.userId}
                                        aria-describedby="userIdHelpBlock" 
                                    />
                                    <Button variant="dark"><Icon.Search /> Find User</Button>
                                    <Form.Control.Feedback type="invalid">
                                    {errors.userId}
                                </Form.Control.Feedback>
                                </InputGroup>
                                <Form.Text id="userIdHelpBlock" muted>
                                    Please click "Find User" to fill out the details.
                                </Form.Text>
                            </Form.Group>
                            <Form.Group controlId="userName">
                                <Form.Label>User Name</Form.Label>
                                <Form.Control 
                                    placeholder="User Name"
                                    type="text" 
                                    name="userName"
                                    value={values.userName}
                                    onChange={handleChange}
                                    isInvalid={!!errors.userName}
                                />
                                <Form.Control.Feedback type="invalid">
                                    {errors.userName}
                                </Form.Control.Feedback>
                            </Form.Group>
                            <Form.Group controlId="userDOB">
                                <Form.Label>Date of Birth</Form.Label>
                                <Datetime
                                    inputProps={{
                                        placeholder: 'DOB',
                                        id: 'userDOB',
                                        name: 'userDOB',
                                    }}
                                    dateFormat="DD-MM-YYYY"
                                    timeFormat={false}
                                    value={values.userDOB}
                                    isValidDate={validDOB}
                                    onChange={(dateFromValue) => {
                                            setFieldValue('userDOB', dateFromValue);
                                        }
                                    }
                                    isInvalid={!!errors.userDOB}
                                />
                                <Form.Control.Feedback type="invalid">
                                    {errors.userDOB}
                                </Form.Control.Feedback>
                            </Form.Group>
                            <div style={{clear: 'both'}}></div>
                            <br></br>
                            <div className='text-center'>
                                <Button variant="dark" type="reset">Reset Form</Button>{' '}
                                <Button variant="success" type="submit">Save</Button>
                            </div>
                        </Form> 
                    </Col>
                )}
                </Formik>
            </Row>
        </Container>
        </>
    );
}
export default AddWorkload;

Validation for userId and userName is working properly. But I can't get the validation to work for userDOB. I also tried yup.date() but it doesn't work. react-datetime uses moment.js. So, what type to use for the schema and how to get the validation working for that compenent.

Any help would be appreciated.

Thanks


Solution

  • I found my issue. Its because Form.Control.Feedback doesn't correspond to the component Datetime.

    So, I removed the Form.Control.Feedback and replaced that with a custom div to display the error message for the Datetime component.

    <Form.Group controlId="patientDOB">
        <Form.Label>Date of Birth</Form.Label>
        <Datetime
            inputProps={{
                placeholder: 'DD-MM-YYYY',
                id: 'userDOB',
                name: 'userDOB',
                className: formik.errors.userDOB && formik.touched.userDOB ? "form-control is-invalid": "form-control"
            }}
            closeOnSelect={true}
            dateFormat="DD-MM-YYYY"
            timeFormat={false}
            value={formik.values.userDOB}
            isValidDate={validDOB}
            onChange={(dateFromValue) => {
                            formik.setFieldValue('userDOB', moment(dateFromValue).format('DD-MM-YYYY'));
                    }
            }
            renderInput={(props) => {
                    return <input {...props} value={(formik.values.userDOB) ? props.value : ''} />
            }}
        />
        {formik.errors.userDOB && formik.touched.userDOB ? (
            <div className="text-danger" style={{fontSize: '0.875em'}}>{ formik.errors.userDOB }</div>
        ) : null}
     </Form.Group>