0

I have a datepicker component that I can use to select a range of startdate and enddate. I then integrated it with formik in another component where I want to use it. It does select date-time correctly. However, it doesn't display the selected data. I purposely did not integrate formik inside the datepicker component So I can easily reuse it in other components.

datepicker component:

import { useState } from 'react'
import DatePicker from 'react-datepicker'
import 'react-datepicker/dist/react-datepicker.css'
import { StyledDatePickerContent, StyledDatePickerWrapper } from './style'

export const TableDatePicker = ({ startName, endName }) => {
  const [startDate, setStartDate] = useState(null)
  const [endDate, setEndDate] = useState(null)

  return (
    <StyledDatePickerWrapper>
      <StyledDatePickerContent>
        <label className="accordion-label">Start</label>
        <DatePicker
          isClearable
          placeholderText="Select Start Date"
          name={startName}
          showTimeSelect
          dateFormat="MMMM d, yyyy h:mmaa"
          selected={startDate}
          selectsStart
          startDate={startDate}
          endDate={endDate}
          maxDate={endDate}
          onChange={(date) => setStartDate(date)}
        />
      </StyledDatePickerContent>
      <StyledDatePickerContent>
        <label className="accordion-label">End</label>
        <DatePicker
          isClearable
          placeholderText="Select End Date"
          name={endName}
          showTimeSelect
          dateFormat="MMMM d, yyyy h:mmaa"
          selected={endDate}
          selectsEnd
          startDate={startDate}
          endDate={endDate}
          minDate={startDate}
          onChange={(date) => setEndDate(date)}
          filterTime={(d) => {
            return startDate < d
          }}
        />
      </StyledDatePickerContent>
    </StyledDatePickerWrapper>
  )
}

Component where I'm using the datepicker with formik:

import React, { useImperativeHandle, useState } from 'react';
import { useFormik } from 'formik';
import * as Yup from 'yup';
import { TableDatePicker } from '../../../../components/DatePickerField/DatePickerField';

const ParkingTypeForm = ({ onChange, refId }) => {
  const [show, setShow] = useState(false);

  const formik = useFormik({
    initialValues: {
      reservation_start_datetime: '',
      reservation_end_datetime: '',
    },
    validationSchema: Yup.object({
      reservation_start_datetime: Yup.string().required(
        'This field is required'
      ),
      reservation_end_datetime: Yup.string().required('This field is required'),
    }),
    onSubmit: (e) => {
      e.preventDefault();
      watchForm();
      console.log('formikValues', formik.values);
      setShow(true);
    },
  });

  useImperativeHandle(refId, () => ({
    Submit: async () => {
      await formik.submitForm();
    },
  }));

  function watchForm() {
    if (onChange) {
      onChange({
        values: formik.values,
        validated: formik.isSubmitting
          ? Object.keys(formik.errors).length === 0
          : false,
      });
    }
  }

  const handleParkingEdit = () => {
    setShow(false);
    document?.getElementById('panelsStayOpen-headingTwo')?.children[0]?.click();
  };

  return (
      <div className={`${show ? 'remove' : 'active'} accordion-item show`}>
        <h2 className="accordion-header" id="panelsStayOpen-headingTwo">
          <button
            className="accordion-button"
            type="button"
            data-bs-toggle="collapse"
            data-bs-target="#panelsStayOpen-collapseTwo"
            aria-expanded="false"
            aria-controls="panelsStayOpen-collapseTwo"
          >
            <span className="number">1</span> Parking Type
          </button>
        </h2>
        <div
          id="panelsStayOpen-collapseTwo"
          className="accordion-collapse collapse show"
          aria-labelledby="panelsStayOpen-headingTwo"
        >
          <div className="accordion-body">
            <form ref={refId}>
              <div className={'form'}>
                {/* <h3>Form A</h3> */}
                <div>
                  <label>Parking Type</label>
                  <TableDatePicker
                    startName="reservation_start_datetime"
                    endName="reservation_end_datetime"
                    value={`
                    ${formik.values.reservation_start_datetime}, 
                     ${formik.values.reservation_end_datetime}
                    `}
                    onBlur={formik.handleBlur}
                    onChange={formik.handleChange}
                  />
                  {formik.errors.startName && (
                    <div style={{ color: 'red' }}>
                      <small>{formik.errors.startName}</small>
                    </div>
                  )}
                  {formik.errors.endName && (
                    <div style={{ color: 'red' }}>
                      <small>{formik.errors.endName}</small>
                    </div>
                  )}
                </div>
                <pre>{JSON.stringify(formik.values, null, 2)}</pre>
              </div>
              <div className="btn-group">
                <button type="submit" className="submitBtn">
                  Save & Continue
                </button>
              </div>
            </form>
          </div>
        </div>
      </div>
  );
};

export default ParkingTypeForm;

I really don't know what I'm missing?

simper
  • 19
  • 9

1 Answers1

0

You should do some changes in your datepicker component

import { useState } from 'react'
import DatePicker from 'react-datepicker'

import { useField, useFormikContext } from "formik";    //Change-----------------------

import 'react-datepicker/dist/react-datepicker.css'
import { StyledDatePickerContent, StyledDatePickerWrapper } from './style'

export const TableDatePicker = ({ startName, endName }) => {

  const { setFieldValue } = useFormikContext();
  const [field1] = useField(startName);
  const [field1] = useField(endName);

  const [startDate, setStartDate] = useState(field1.value || null)
  const [endDate, setEndDate] = useState(field2.value || null)

  return (
    <StyledDatePickerWrapper>
      <StyledDatePickerContent>
        <label className="accordion-label">Start</label>
        <DatePicker
          {...field1}
          isClearable
          placeholderText="Select Start Date"
          name={startName}
          showTimeSelect
          dateFormat="MMMM d, yyyy h:mmaa"
          selected={startDate}
          selectsStart
          startDate={startDate}
          endDate={endDate}
          maxDate={endDate}
          onChange={(date) => {setFieldValue(`${name}`, date);
                              setStartDate(date)}}
            />
          </StyledDatePickerContent>
          <StyledDatePickerContent>
            <label className="accordion-label">End</label>
            <DatePicker
              {...field2}
              isClearable
              placeholderText="Select End Date"
              name={endName}
              showTimeSelect
              dateFormat="MMMM d, yyyy h:mmaa"
              selected={endDate}
              selectsEnd
              startDate={startDate}
              endDate={endDate}
              minDate={startDate}
              onChange={(date) => {setFieldValue(`${name}`, date);
                              setEndDate(date)}}
              filterTime={(d) => {
                return startDate < d
              }}
        />
      </StyledDatePickerContent>
    </StyledDatePickerWrapper>
  )
}

Now do some changes where you use this component

<TableDatePicker
                    startName="reservation_start_datetime"
                    endName="reservation_end_datetime"
                    
                  />
                  {formik.touched. reservation_start_datetime && formik.errors.reservation_start_datetime && (
                    <div style={{ color: 'red' }}>
                      <small>{formik.errors.startName}</small>
                    </div>
                  )}
                  {formik.touched.reservation_end_datetime && formik.errors.reservation_end_datetime && (
                    <div style={{ color: 'red' }}>
                      <small>{formik.errors.endName}</small>
                    </div>
                  )}