Formulare und Validierung

Formulare und Validierung

Möglichkeiten:

  • eingebaute Funktionalität von HTML-Elementen
  • eingebaute Funktionalität von Komponentenlibraries
  • Formular-Libraries (react-hook-form, formik)
  • eigener Validierungs-Code

Formulare und Validierung

eingebaute Funktionalität von HTML:

<input required={true} minlength={4} />

Formulare und Validierung

Wann kann ein Input validiert werden?

  • wenn das Formular submittet wird (submit)
  • wenn ein Eingabefeld den Fokus verliert (blur)
  • bei jeder Änderung eines Wertes (change)

Der beste Zugang hängt vom Anwendungsfall ab

Validierung: Beispiele

Validierung bei jeder Änderung:

const NewsletterSignup = () => {
  const [email, setEmail] = useState('');
  const emailValid = isEmail(email);

  // ...
  // display a form
  // and optionally a warning about an invalid email
};

Validierung: Beispiele

Validierung bei blur:

const NewsletterSignup = () => {
  const [email, setEmail] = useState('');
  const [emailValid, setEmailValid] = useState(true);
  // call from onBlur:
  const validateEmail = () => {
    setEmailValid(isEmail(email));
  };

  // ...
  // display a form
  // and optionally a warning about an invalid email
};

Validierung: Beispiele

vollständiges Beispiel: Validierung bei blur und submit

const NewsletterSignup = () => {
  const [email, setEmail] = useState('');
  const [emailValid, setEmailValid] = useState(true);
  const validateEmail = () => {
    setEmailValid(isEmail(email));
  };

  return (
    <form
      onSubmit={(event) => {
        event.preventDefault();
        validateEmail();
        if (isEmail(email)) {
          console.log(`Signed up: ${email}`);
        }
      }}
    >
      <input
        value={email}
        onChange={(event) => setEmail(event.target.value)}
        onBlur={() => validateEmail()}
      />
      <button>sign up</button>
      {!emailValid ? <div>invalid email</div> : null}
    </form>
  );
};

const isEmail = (email) =>
  email.match(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i);

Validierung

komplexere Schemata zur Validierung sind möglich

Beispiel: erste Validierung eines Feldes beim ersten blur, danach live-Validierung bei jedem change

Formular-Libraries

Formular-Libraries

Beispiele:

  • react-hook-form (basiert auf einem React Hook)
  • formik (basiert auf React-Komponenten)

Funktionalität:

  • Validierung
  • Verwalten von Formulardaten
  • Vereinfachung des Submit-Handlers

react-hook-form

react-hook-form behält Inputdaten nicht im React State

Vorteile: schneller, einfacher

Nachteile: weicht von üblichen React-Konzepten ab (benutzt refs anstatt state)

react-hook-form

import { useForm } from 'react-hook-form';

function NewsletterSignup() {
  const { register, handleSubmit, formState } = useForm();
  return (
    <form onSubmit={handleSubmit(console.log)}>
      <input
        {...register('email', {
          required: true,
          pattern: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
        })}
      />
      {formState.errors.email ? (
        <div>invalid email</div>
      ) : null}
      <button type="submit">sign up for newsletter</button>
    </form>
  );
}

Bemerkung: react-hook-form verwendet eine callback ref, um auf das input-Element zuzugreifen

react-hook-form: register

Die register-Funktion kann Parameter für die Validierung erhalten:

  • required
  • min, max
  • minLength, maxLength
  • pattern
  • validate

react-hook-form: errors

Das Objekt formState.errors gibt Fehler für registrierte Inputs an

<input {...register('email')} />
formState.errors.email ? <div>invalid email</div> : null;
!formState.isValid ? <div>invalid form entries</div> : null;

react-hook-form: handleSubmit

handleSubmit validiert Formulardaten und gibt diese an eine Funktion weiter, wenn sie gültig sind

<form
  onSubmit={handleSubmit((data) => {
    console.log(data.email);
  })}
>
  ...
</form>

react-hook-form: mode

useForm({ mode: 'onBlur' });

mode: wann soll ein Wert zum ersten Mal validiert werden?

  • onSubmit (Standard)
  • onBlur - wenn der Input den Fokus verliert oder bei Submit
  • onTouched - wenn der Input den Fokus verliert (wechselt nicht zu reValidateMode) oder bei Submit
  • onChange - wenn sich der Input ändert oder bei Submit
  • all - wenn der Input sich ändert oder wenn er den Fokus verliert, ohne sich geändert zu haben

react-hook-form: mode

reValidateMode: wenn das Form submittet wurde und ein Fehler auftrat, wann sollte der Wert erneut validiert werden?

  • onSubmit
  • onBlur
  • onChange (Standard)

react-hook-form: reset, getValues

const {
  register,
  errors,
  handleSubmit,
  reset,
  getValues,
} = useForm();

formik

import { Formik, Form, Field, ErrorMessage } from 'formik';

const NewsletterRegistration = () => (
  <Formik
    initialValues={{ email: '' }}
    onSubmit={(values) => console.log(values)}
    validate={(values) => {
      const errors = {};
      if (!isEmail(values.email)) {
        errors.email = 'invalid email';
      }
      return errors;
    }}
  >
    {(props) => (
      <Form>
        <Field type="email" name="email" />
        <button type="submit" disabled={!props.isValid}>
          subscribe
        </button>
        <ErrorMessage name="email" component="div" />
      </Form>
    )}
  </Formik>
);

const isEmail = (email) =>
  email.match(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i);