Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change structure for form definition #26

Merged
merged 4 commits into from
Jan 14, 2023
Merged

Change structure for form definition #26

merged 4 commits into from
Jan 14, 2023

Conversation

brophdawg11
Copy link
Owner

@brophdawg11 brophdawg11 commented Jan 14, 2023

⚠️ This is a breaking Change

Previously, we went with a very minimal API for defining your form validations (which are just attributes in the built-in cases):

const formValidations = {
  firstName: {
    required: true,
    maxLength: 50,
  },
  lastName: {
    required: true,
    maxLength: 50,
  },
};

But as we scaled up functionality, this started to become a bit limiting:

  1. Adding custom validations directly alongside built-in attributes makes type restrictions harder, since you can't restrict the object keys to only those built-in HTML validation attributes.
  2. There's no room for custom error messages, so they needed to go in a separate object. Being able to colocate them with their specific validations would be nice.
  3. Typings got really nasty when looking to implement additional, seemingly simple, functionality

This PR moves to a new more-comprehensive API for defining your form information with 2 major changes:

  1. Built-in validations are separated from custom validations
  2. Error messages can be included at either the field level or the global level

A new form definition would looks look like:

import type { ErrorMessage, InputDefinition } from "remix-validity-state";

// Define your schema so we can properly infer types on things such as `serverFormData.inputs`
interface MyFormSchema {
  inputs: {
    username: InputDefinition;
    emailAddress: InputDefinition;
  };
  errorMessages: {
    tooShort: ErrorMessage;
  };
}

let formDefinition: FormSchema = {
  inputs: {
    username: {
      validationAttrs: {  // 👈 Built-in HTML validations
        required: true,
        minLength: 5,
        pattern: "^[a-zA-Z]+$",
      },
    },
    emailAddress: {
      validationAttrs: {
        type: "email",
        required: true,
      },
      customValidations: {  // 👈 Custom validations
        async uniqueEmail(value) {
          await new Promise((r) => setTimeout(r, 1000));
          return value !== "john@doe.com" && value !== "jane@doe.com";
        },
      },
      errorMessages: {  // 👈 Field-level error messages
        uniqueEmail(attrValue, name, value) {
          return `The email address "${value}" is already in use!`;
        },
      },
    },
  },
  errorMessages: {  // 👈 Global error messages
    tooShort: (attrValue) => `Field must be at least ${attrValue} characters long`,
  },
};

My hope is that this makes things like #8 and #21 a good bit easier 🤞

@brophdawg11
Copy link
Owner Author

This also includes the change from #17

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant