React, Formik, Да: Как зарегистрировать касание при использовании средства выбора календаря

#reactjs #typescript #formik #yup

Вопрос:

Я новичок во всех трех технологиях и искал ответ, но не смог его найти. Примечание: Я упростил файл, чтобы облегчить его анализ во время чтения, надеюсь, я не вырезал ничего важного для отладки.

Я хотел бы, чтобы моя форма регистрировалась как тронутая, когда пользователь нажимает, чтобы выбрать дату с помощью средства выбора календаря. В настоящее время я могу отобразить ошибку в тексте справки, но она не изменяет стиль формы так же, как это произойдет, если пользователь нажмет на поле, как если бы он намеревался ввести его сам.

 import React, { FC, useRef } from "react";
import { Formik, Form, Field } from "formik";
import { KeyboardDatePicker } from "formik-material-ui-pickers";
import * as Yup from "yup";
import moment from "moment";
import { ReportConfig } from "../ReportConfig";

export type DProps = {
  type: Type | null,
  currentConfig: ReportConfig | null,
};

export const Dialog: FC<DProps> = ({ currentConfig }) => {
  const form: any = useRef(null); // Reference to formik form

  let initialValues = {
    periodStart: moment(currentConfig?.periodStart),
    periodEnd: moment(currentConfig?.periodEnd),
  };

  return (
    <Formik
      innerRef={form}
      initialValues={initialValues}
      validationSchema={Yup.object().shape({
        periodStart: Yup.date()
          .typeError("Enter a valid date.")
          .max(Yup.ref("periodEnd"), "Must be before End.")
          .required("Required"),
        periodEnd: Yup.date()
          .typeError("Enter a valid date.")
          .min(Yup.ref("periodStart"), "Must be after Start.")
          .required("Required"),
      })}
    >
      {({ values, errors, touched, handleBlur }) => (
        <Form>
          <Field
            variant="inline"
            autoOk
            name={"periodStart"}
            value={values.periodStart}
            label="Start Date"
            inputVariant="outlined"
            component={KeyboardDatePicker}
            format="MM/DD/YYYY"
            onBlur={handleBlur}
            error={touched.periodEnd amp;amp; errors.periodStart !== undefined}
            helperText={errors.periodStart}
          />
          <Field
            variant="inline"
            autoOk
            name={"periodEnd"}
            value={values.periodEnd}
            label="End Date"
            inputVariant="outlined"
            component={KeyboardDatePicker}
            format="MM/DD/YYYY"
            onBlur={handleBlur}
            error={touched.periodEnd amp;amp; errors.periodEnd !== undefined}
            helperText={errors.periodEnd}
          />
        </Form>
      )}
    </Formik>
  );
};
 

В настоящее время отображается таким образом, когда происходит ошибка даты, но пользователь использовал календарь для выбора даты
против
Должно отображаться таким образом независимо от метода, используемого для ввода даты

Ответ №1:

Я все понял. Вы должны добавить setFieldTouched и предоставить ему анонимную функцию, которая устанавливает значение true.

 import React, { FC, useRef } from "react";
import { Formik, Form, Field } from "formik";
import { KeyboardDatePicker } from "formik-material-ui-pickers";
import * as Yup from "yup";
import moment from "moment";
import { ReportConfig } from "../ReportConfig";

export type DProps = {
  type: Type | null,
  currentConfig: ReportConfig | null,
};

export const Dialog: FC<DProps> = ({ currentConfig }) => {
  const form: any = useRef(null); // Reference to formik form

  let initialValues = {
    periodStart: moment(currentConfig?.periodStart),
    periodEnd: moment(currentConfig?.periodEnd),
  };

  return (
    <Formik
      innerRef={form}
      initialValues={initialValues}
      validationSchema={Yup.object().shape({
        periodStart: Yup.date()
          .typeError("Enter a valid date.")
          .max(Yup.ref("periodEnd"), "Must be before End.")
          .required("Required"),
        periodEnd: Yup.date()
          .typeError("Enter a valid date.")
          .min(Yup.ref("periodStart"), "Must be after Start.")
          .required("Required"),
      })}
    >
      {({ values, errors, touched, handleBlur, setFieldTouched }) => (
        <Form>
          <Field
            variant="inline"
            autoOk
            name={"periodStart"}
            value={values.periodStart}
            label="Start Date"
            inputVariant="outlined"
            component={KeyboardDatePicker}
            format="MM/DD/YYYY"
            onBlur={handleBlur}
            error={touched.periodEnd amp;amp; errors.periodStart !== undefined}
            helperText={errors.periodStart}
            onClick={() => setFieldTouched("periodStart", true)}
          />
          <Field
            variant="inline"
            autoOk
            name={"periodEnd"}
            value={values.periodEnd}
            label="End Date"
            inputVariant="outlined"
            component={KeyboardDatePicker}
            format="MM/DD/YYYY"
            onBlur={handleBlur}
            error={touched.periodEnd amp;amp; errors.periodEnd !== undefined}
            helperText={errors.periodEnd}
            onClick={() => setFieldTouched("periodEnd", true)}
          />
        </Form>
      )}
    </Formik>
  );
};