Form Validation In Remix Using Yup

aaronksaunders

Aaron K Saunders

Posted on January 15, 2022

Form Validation In Remix Using Yup

Overview

Simple application showing how to implement form validation in your Remix application and Yup

I use Yup with React-Hook-From and I was looking to see if I could use it with Remix... I got it working and I thought it would be interesting to share in an video

Remix is a full stack web framework that lets you focus on the user interface and work back through web fundamentals to deliver a fast, slick, and resilient user experience.

The Video

Source Code

import { Form, Link, ActionFunction, redirect, useActionData } from "remix";
import * as Yup from "yup";
import { addProject } from "./dataService";

/**
 *
 * @param formData
 * @returns
 */
const validateForm = async (formData: FormData) => {

  const getValidationErrors = (err: any) => {
    const validationErrors = {} as any;

    err.inner.forEach((error: any) => {
      if (error.path) {
        validationErrors[error.path] = error.message;
      }
    });

    return validationErrors;
  };

  // convert form into JSON object
  const formJSON: { [key: string]: any } = {};
  for (var key of formData.keys()) {
    formJSON[key] = formData.get(key);
  }

  // Yup schema for the object that I am trying to validate
  const projectSchema = Yup.object({
    name: Yup.string().required("Name is a required field").nullable(),
    email: Yup.string()
      .email("This is not a valid email")
      .required("Email is a required field")
      .nullable(),
    description: Yup.string()
      .required("Description is a required field")
      .nullable(),
    createdOn: Yup.date().default(() => new Date()),
  });

  // validate the object and throw error if not valid
  try {
    const project = await projectSchema.validate(formJSON, { abortEarly: false });
    return project;
  } catch (error) {
    throw getValidationErrors(error);
  }
};

/**
 * 
 * @param param0 
 * @returns 
 */
export const action: ActionFunction = async ({ request }) => {
  const formData = await request.formData();

  try {
    // validate
    const project = await validateForm(formData);
    //save
    const newProject = await addProject(project);
    return redirect(`/projects/${newProject.id}`);
  } catch (errors) {
    return { errors };
  }
};

export default function NewProject() {
  // data returned after submitting the form
  const actionData = useActionData();

  return (
    <div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
    <h2>Remix Form Validation With Yup</h2>
    <Form method="post" action="/new-item" noValidate={true}>
      <p>
        <label>
          Name:{" "}
          <input
            name="name"
            type="text"
            style={{ borderColor: actionData?.errors["name"] && "red" }}
          />
        </label>
        <div>{actionData?.errors["name"]}</div>
      </p>
      <p>
        <label>
          Email:{" "}
          <input
            name="email"
            type="email"
            style={{ borderColor: actionData?.errors["email"] && "red" }}
          />
        </label>
        <div>{actionData?.errors["email"]}</div>
      </p>
      <p>
        <label>
          Description:
          <br />
          <textarea
            name="description"
            style={{ borderColor: actionData?.errors["description"] && "red" }}
          />
        </label>
        <div>{actionData?.errors["description"]}</div>
      </p>
      <p>
        <button type="submit">CREATE</button>
        <Link to={"/"} style={{ marginLeft: 12 }}>
          <button type="submit">CANCEL</button>
        </Link>
      </p>
      <pre>{JSON.stringify(actionData?.errors, null, 2)}</pre>
    </Form>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode
💖 💪 🙅 🚩
aaronksaunders
Aaron K Saunders

Posted on January 15, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Form Validation In Remix Using Yup
remix Form Validation In Remix Using Yup

January 15, 2022