Parcourir la source

Focus on first error field on validation finish

Leszek Wiesner il y a 4 ans
Parent
commit
aefbb7ea43

+ 18 - 2
pioneer/packages/joy-proposals/src/forms/GenericProposalForm.tsx

@@ -1,4 +1,4 @@
-import React, { useEffect, useState } from 'react';
+import React, { useEffect, useState, useRef } from 'react';
 import { FormikProps, WithFormikConfig } from 'formik';
 import { Form, Icon, Button, Message } from 'semantic-ui-react';
 import { getFormErrorLabelsProps } from './errorHandling';
@@ -100,6 +100,7 @@ export const GenericProposalForm: React.FunctionComponent<GenericFormInnerProps>
   } = props;
   const errorLabelsProps = getFormErrorLabelsProps<GenericFormValues>(errors, touched);
   const [afterSubmit, setAfterSubmit] = useState(null as (() => () => void) | null);
+  const formContainerRef = useRef<HTMLDivElement>(null);
 
   // After-submit effect
   // (with current version of Formik, there seems to be no other viable way to use ie. for sendTx)
@@ -113,6 +114,21 @@ export const GenericProposalForm: React.FunctionComponent<GenericFormInnerProps>
     }
   }, [isValidating, isValid, afterSubmit]);
 
+  // Focus first error field when isValidating changes to false (which happens after form is validated)
+  // (operates directly on DOM)
+  useEffect(() => {
+    if (!isValidating && formContainerRef.current !== null) {
+      const [errorField] = formContainerRef.current.getElementsByClassName('error field');
+      if (errorField) {
+        errorField.scrollIntoView({ behavior: 'smooth' });
+        const [errorInput] = errorField.querySelectorAll('input,textarea');
+        if (errorInput) {
+          (errorInput as (HTMLInputElement | HTMLTextAreaElement)).focus();
+        }
+      }
+    }
+  }, [isValidating]);
+
   // Replaces standard submit handler (in order to work with TxButton)
   const onTxButtonClick = (sendTx: () => void) => {
     submitForm();
@@ -144,7 +160,7 @@ export const GenericProposalForm: React.FunctionComponent<GenericFormInnerProps>
     proposalsConsts[proposalType].stake;
 
   return (
-    <div className="Forms">
+    <div className="Forms" ref={formContainerRef}>
       <Form
         className="proposal-form"
         onSubmit={txMethod