npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@quatrecentquatre/form-me

v5.0.0

Published

FormMe =======

Downloads

66

Readme

FormMe

Helps you handle recurrent form manipulation on submit

Installation

First of all, you must allow your project to download the package.

To do so, make sure you have a .npmrc file (at the same level as the package.json file) containing the following code:

//registry.npmjs.org/:_authToken=${NPM_TOKEN}

Replace ${NPM_TOKEN} by the token you will find in Zoho behind NPM - Clé installation package.

Then, add the package to your project:

$ yarn add @quatrecentquatre/form-me

Usage

First, import the library in your main JS file:

import "@quatrecentquatre/form-me";

Here you go ! You're now ready to use FormMe.

To create a form and to add validation to it, here's the things you need to do to make it work.

  • Create your HTML form
  • Create your Javascript view.

HTML Form

You'll need to create an HTML form with a special attribute data-me-form with the javascript class name you'll create as value.

Example:

<form method="post" action="#" ajax="true" data-me-form="BasicForm">
  <div>
    <label for="name">Name</label>
    <input type="text" name="name" id="name" placeholder="name" />
    <p class="hide error" aria-hidden="true" role="alert" aria-atomic="true">
      Field error message
    </p>
  </div>
  <div>
    <label for="email">Email</label>
    <input type="text" name="email" id="email" placeholder="email" />
    <p class="hide error" aria-hidden="true" role="alert" aria-atomic="true">
      Field error message
    </p>
  </div>
  <input type="submit" />
</form>

Here's are the attribute to set on your form element. Not required all required but might be for the best to set them.

  • method : (Mandatory) POST or GET
  • ajax : If added, need to be set to "true". If ajax not needed, just remove the attribute from the DOM
  • action : URL for the request

There's additional attributes that can be set on the form

  • recaptcha : (Boolean) True | False to determine if you want recaptcha active
  • recaptcha-action : (String) If you want to specify the action passed to recaptcha.
  • data-me-form-data : (Object) If you want to pass data from the html to js

Javascript view

You'll need to create a Javascript file with a class that extends the basic Form class.

In the constructor, you'll have to add fields that need validation. For all possible option for a single field, please refer to the field section.

Example:

// We use yup for validation so we've set the import in the example too but needs to be modify to fit your needs.
import { string } from "yup";
import { FormBase } from "@quatrecentquatre/form-me";

export class BasicForm extends FormBase {
  constructor(options) {
    super(options);

    this.addFields([
      {
        name: "name",
        validationSchema: string().required(),
        $error: document
          .querySelector('[name="name"]')
          .parentElement.parentElement.querySelector(".error"),
      },
      {
        name: "email",
        validationSchema: string().required(),
        $error: document
          .querySelector('[name="email"]')
          .parentElement.parentElement.querySelector(".error"),
      },
    ]);
  }
}

Me.forms["BasicForm"] = BasicForm;

View params

You can have default params set for your form view. The way to do it is to declare the defaults function and return the object of defaults value you want. These params can be useful if you want to add another layer to fit your particular need with a re-usable base class. These params will merge with the data-me-form-data that you can set on the HTML side.

Example:

import { string } from "yup";
import { FormBase } from "@quatrecentquatre/form-me";

class BasicForm extends FormBase {
  defaults() {
    return {
      name: "username",
    };
  }
  constructor(options) {
    super(options);

    this.addFields([
      {
        name: "name",
        validationSchema: string().required(),
        $error: document
          .querySelector('[name="name"]')
          .parentElement.parentElement.querySelector(".error"),
      },
      {
        name: "email",
        validationSchema: string().required(),
        $error: document
          .querySelector('[name="email"]')
          .parentElement.parentElement.querySelector(".error"),
      },
    ]);
  }
}

Me.forms["BasicForm"] = BasicForm;

The defaults params can be changed / extended in your DOM declaration too.

Example:

<form
  method="post"
  action="#"
  ajax="true"
  data-me-form="BasicForm"
  data-me-form-data='{"extend": "extend"}'
>
  <div>
    <label for="name">Name</label>
    <input type="text" name="name" id="name" placeholder="name" />
    <p class="hide error" aria-hidden="true" role="alert" aria-atomic="true">
      Error
    </p>
  </div>
  <div>
    <label for="email">Email</label>
    <input type="text" name="email" id="email" placeholder="email" />
    <p class="hide error" aria-hidden="true" role="alert" aria-atomic="true">
      Error
    </p>
  </div>
  <input type="submit" />
</form>

Field params

  • name: (String) [Required] Name attribute of the field
  • validationSchema: (Yup Schema)[Required] // See https://github.com/jquense/yup
  • $error: (HtmlElement) Single element that will automatically show on error
  • maskOptions: (Object IMask Options) // See https://imask.js.org/
  • format: (Function) Function to format the field value before sending data through ajax call

Customization

Validation

If you are looking to add a custom validation on one of the field, you can use the .test function. Follow the Yup documentation at https://github.com/jquense/yup#schematestname-string-message-string--function--any-test-function-schema

Field example:

{
    name: 'file',
    validationSchema: mixed()
        .test('is-valid-type', 'Not a valid file type', (value) => value && value.name.toLowerCase().split('.').at(-1) === 'jpg')
        .test('is-valid-size', 'Max allowed size is 1MB', (value) => value && value.size <= 1024000),
    $error: document.querySelector('[name="file"]').parentElement.parentElement.querySelector('.error'),
}

Format

If you have to format a field value before sending it through the ajax call you can use a custom function to format the value. The function will automatically receive the field value.

import { string } from "yup";
import { FormBase } from "@quatrecentquatre/form-me";

class BasicForm extends FormBase {
  constructor(options) {
    super(options);

    this.addFields([
      {
        name: "name",
        validationSchema: string().required(),
        $error: document
          .querySelector('[name="name"]')
          .parentElement.parentElement.querySelector(".error"),
        format: this.toUppercase.bind(this),
      },
      {
        name: "email",
        validationSchema: string().required(),
        $error: document
          .querySelector('[name="email"]')
          .parentElement.parentElement.querySelector(".error"),
      },
    ]);
  }

  toUppercase(value) {
    return value.toUpperCase();
  }
}

Me.forms["BasicForm"] = BasicForm;

Empty values

By default, if a field is not required and empty, FormMe will exclude it from the values sent. If you want to allow empty values you can use this.acceptSendingEmptyValues = true

Functions

Here's a list of some functions that can be modified or to overwrite. You can see in the lib all functions that can be changed if you want to.

submitHandler(e)

Will be triggered by clickSubmitHandler and if the user submit by hitting enter. Will look if ajax is defined or not to trigger the right submit.

handleValidationSuccess()

If no error found, it will go through this function. Will add a class if you want to apply new styles, it will check if recaptcha is present and if need to be validated and then send a formatted version of the form data to the function that will use the fetch api to send the data.

handleValidationError()

If error found during validation, it will pass here to show fields with error to the user.

setFieldState(field, error)

Set error state of the field. We base the logic on the error type to display the right error message already present in the HTML. Overwrite the function to handle what needs to be set if you want to do custom manipulation on error handling.

resetFieldState(field)

As the name says, restore field value to an empty one. Based on the data-me-form-error to add the hide class. Overwrite the function to handle what needs to be reset if you want to do custom manipulation.

ajaxSuccess(response)

As the function name says it, when the call return a success, it goes in and restore the form, add a class to let the dev display a message with css only. You can overwrite this function to have a custom handle of the success provided by the backend.

ajaxError(error)

As the function name says it, when the call return an error, it goes in and add a class to let the dev display an error message only with css. You can overwrite this function to have a custom handle of the error provided by the backend and handle different error that can be returned.

ajaxComplete()

This function exist to handle all code that should be run if a success or an error is triggered. If you need to do anything no matter what the response is, you can overwrite this function.

reset()

This will reset fields to original empty value

Modify functions

To extend or completely modify a function simple declare it in your new class like the following example. Use super if you want the original code to run before the code you will add.

Example:

import { string } from "yup";
import { FormBase } from "@quatrecentquatre/form-me";

class BasicForm extends FormBase {
  constructor(options) {
    super(options);

    this.addFields([
      {
        name: "name",
        validationSchema: string().required(),
        $error: document
          .querySelector('[name="name"]')
          .parentElement.parentElement.querySelector(".error"),
        format: this.toUppercase.bind(this),
      },
      {
        name: "email",
        validationSchema: string().required(),
        $error: document
          .querySelector('[name="email"]')
          .parentElement.parentElement.querySelector(".error"),
      },
    ]);
  }

  resetFieldState(field) {
    super.resetFieldState(field);
    // Custom code to run after field pass validation success
  }
}

Me.forms["BasicForm"] = BasicForm;

Errors

Looking to handle error message for your fields? There is a simple way to handle them. Simply add the error attribute to the field object you want an error to show with the element you want to see when the error occur.

Add the element you want to show on error in your HTML

<form method="post" action="#" ajax="true" data-me-form="BasicForm">
  <div>
    <label for="name">Name</label>
    <input type="text" name="name" id="name" placeholder="name" />
    <p class="hide error" aria-hidden="true" role="alert" aria-atomic="true">
      Field error message
    </p>
  </div>
  <input type="submit" />
</form>
this.addFields([
  {
    name: "name",
    $error: document
      .querySelector('[name="name"]')
      .parentElement.parentElement.querySelector(".error"),
  },
]);

Multiple error message?

If you're looking to handle multiple case for one field you need to do it by yourself. Since we use YUP for validation. FormMe will detect if there's any data-me-form-error attribute with the right value based on the error type. Ex: Required -> data-me-form-error="required" You can find an example with the email field in the demo.

Submit Button

You can define a custom submit button by adding data-me-form-submit to the desired element. Otherwise, the submit type will be assigned as submit button

Recaptcha v3

If you are loading Recaptcha v3 into your project, FormMe has an automatic detection to ensure recaptcha validation before ajax call.

How does it work?

If you have set ajax="true" on your form and if grecaptcha is defined, FormMe will perform a recaptcha validation before the ajax call.

To perform that validation, FormMe will expect :

  • a window.SETTINGS.RECAPTCHA_SITE_KEY containing the recaptcha site key to use
  • a recaptcha-action attribute on your <form> containing the action to use
  • a <input type="hidden" name="g-recaptcha-response"> into the <form> to store the validation token

In case you have set ajax="true" on your form and grecaptcha is defined but you want to prevent FormMe to perform a recaptcha validation, you can add recaptcha="false" on your <form>

Some case present in the demo

Matching values

If you need to validate fields that needs to have the same value, you can take a look at the schema of the email/email-match

Regex or Mask

If you need to set a mask to set a pattern like for phone, zip code, etc ... you can add a mask. We use Imask. You can add a maskOptions key with a Object as value containing IMask options. You can check the Phone / Tel field that contains Regex and mask.

Regex example

phone: /^(?:\+?1)?[-. ]?\(?[2-9][0-8][0-9]\)?[-. ]?[2-9][0-9]{2}[-. ]?[0-9]{4}$/i;
zipcode: /^[ABCEGHJKLMNPRSTVWXYZ][0-9][ABCEGHJKLMNPRSTVWXYZ]?[ ]?[0-9][ABCEGHJKLMNPRSTVWXYZ][0-9]$/i;

Files

If you need to have a file field, you can check the demo to see how size should be handle and type of files uploaded.