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 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-form-validation-handler

v0.0.7

Published

react-form-validation-handler is a React library for simplifying form validation. It provides a set of utilities and hooks to handle client-side form validation with ease.

Downloads

18

Readme

react-form-validation-handler

react-form-validation-handler is a React library for simplifying form validation. It provides a set of utilities and hooks to handle client-side form validation with ease.

Key features include:

Declarative Validation Rules: Define validation rules in a declarative manner.

Dynamic Validation: Handle dynamic validation based on user input.

Custom Validation Functions: Support for custom validation functions.

# Installation

This package requires React 16.8.4 or later.

Use the package manager npm or yarn to install react-form-validation-handler.

$ npm install react-form-validation-handler

or

$ yarn add react-form-validation-handler

# Basic Example

/* form.js */
import { FormProvider, Form } from "react-form-validation-handler";
export const { useForm, useFormRef } = FormProvider();

/* hook.js */
import { useForm } from "./form.js";
export const useFormHook = () =>
  useForm({
    FORM_CONFIG: {
      name: { isRequired: true },
      age: { min: 18, max: 16 },
    },
  });

/* customInputField.js */
import { useFormConsumer } from "react-form-validation-handler";

export const InputField = React.memo((props) => {
  const { id, name, ...restProps } = props;
  const { inputProps } = useFormConsumer({ id });
  return (
    <div>
      <div>{name}</div>
      <input {...inputProps} {...restProps} />
      {inputProps.error && <span>{inputProps.error}</span>}
    </div>
  );
});

/* basicForm.js */
import { useEffect, useRef } from "react";
import { Form } from "react-form-validation-handler";
import { useFormHook } from "./hook.js";
import { InputField } from "./customInputField.js";
export const BasicForm = () => {
  const { formRef, formId } = useFormHook();
  return (
    <Form.Provider formRef={formRef}>
      <InputField id="name" />
      <InputField id="age" />
      <Button onClick={formRef.validateForm}>Submit</Button>
    </Form.Provider>
  );
};

# Basic usage

# Form Configuration

Note:
- Its required to configure form Provider before start using useForm hook
- Global config (one time configuration)
/* form.js */
import { FormProvider, Form } from "react-form-validation-handler";
import {
  ON_CHANGE,
  ON_BLUR,
  ON_CHANGE,
  ERROR,
  ON_CHANGE_TEXT,
} from "react-form-validation-handler/constants";
const { useForm, useFormRef } = FormProvider({
  ON_CHANGE_KEY: ON_CHANGE /* use ON_CHANGE_TEXT if you are using react-native  */,
  ON_BLUR_KEY: ON_BLUR,
  VALUE_KEY: VALUE,
  ERROR_KEY: ERROR,
});
export { useForm, useFormRef, Form };

Hooks and Components

useForm: A hook for managing form state.

useFormRef: A hook for obtaining a reference to the form.

Form: A form component for use in React components.

# Getting inputprops using hook

/* customInputField.js */
import { useFormConsumer } from "react-form-validation-handler";

const InputField = React.memo((props) => {
  const { id, name, ...restProps } = props;
  const { inputProps } = useFormConsumer({ id });
  return (
    <div>
      <div>{name}</div>
      <input {...inputProps} {...restProps} />
      {inputProps.error && <span>{inputProps.error}</span>}
    </div>
  );
});

Note: Avoiding Unnecessary Re-renders

- One significant advantage of using the context-based implementation provided by react-form-validation-handler is its ability to minimize unnecessary component re-renders on every onChange.

- By managing form state through the FormProvider, components subscribing to the form state will only re-render when relevant form data changes. This can lead to improved performance in scenarios where frequent re-renders are not desired.

# Getting inputprops using context

/* customInputField.js */
import { Form } from "react-form-validation-handler";

export const InputField = React.memo((props) => {
  const { id, name, ...restProps } = props;
  return (
    <Form.Consumer
      id={id}
      inputConfig={{
        isRequired: false,
      }}
    >
      {({ inputProps }) => (
        <div>
          <div>{name}</div>
          <input {...inputProps} {...restProps} />
          {inputProps.error && <span>{inputProps.error}</span>}
        </div>
      )}
    </Form.Consumer>
  );
});

# creating basic form hook config

- Import

/* hook.js */
import { useForm } from "./form.js";

- Form Configuration

Define your form configuration using FORM_CONFIG. Each field in the form has specific validation rules.

const FORM_CONFIG = {
  name: { isRequired: true },
  age: { min: 18, max: 16 },
  company: { isRequired: true },
};

- Initialization

Initialize the form hook using useForm and provide the FORM_CONFIG and initial state.

const initialState = {
  name: "",
}; /* optional -  default state */
export const useFormHook = () =>
  useForm({
    FORM_CONFIG,
    initialState,
  });

Usage

import { useForm } from "./form.js";
const FORM_CONFIG = {
  name: { isRequired: true },
  age: { min: 18, max: 16 },
  company: { isRequired: true },
};
export const useFormHook = () =>
  useForm({
    FORM_CONFIG,
    initialState: {
      name: "",
    },
  });

# using form hook in component

- Import

/* basicForm.js */
import { useEffect, useRef } from "react";
import { useFormHook, Form } from "./hook.js";
import { InputField } from "./customInputField.js";

- Component Definition

The BasicForm component utilizes the useFormHook to manage form state and the Form. Form.Provider to wrap the form elements.

const BasicForm = () => {
  const { formRef, formId } = useFormHook();
  return (
    <Form.Provider formRef={formRef}>
      <InputField id="name" />
      <InputField id="age" />
      <InputField id="company" />
      <Button onClick={formRef.validateForm}>Submit</Button>
    </Form.Provider>
  );
};

Usage

/* basicForm.js */
import { useEffect, useRef } from "react";
import { useFormHook, Form } from "./hook.js";
import { InputField } from "./customInputField.js";

const BasicForm = () => {
  const { formRef, formId } = useFormHook();
  return (
    <Form.Provider formRef={formRef}>
      <InputField id="name" />
      <InputField id="age" />
      <InputField id="company" />
      <Button onClick={formRef.validateForm}>Submit</Button>
    </Form.Provider>
  );
};

export BasicForm;

# creating nested form hook config

- Import

/* basicForm.js */
import { newSchema } from "react-form-validation-handler";
import { useForm } from "./form.js";

- Form Configuration

Define your nested form configuration using newSchema. In this example, we have a person schema with nested properties.

const FORM_CONFIG = {
  person: newSchema({
    name: { isRequired: true },
    age: { min: 18, max: 16 },
    company: {
      isRequired: true,
      inputProps: {
        disabled: true,
      },
    },
  }),
};

- Initialization

Initialize the form hook using useForm and provide the FORM_CONFIG with nested schema.

export const useFormHook = () =>
  useForm({
    FORM_CONFIG,
  });

Usage

/* hook.js */
import { newSchema } from "react-form-validation-handler";
import { useForm } from "./form.js";

const FORM_CONFIG = {
  person: newSchema({
    name: { isRequired: true },
    age: { min: 18, max: 16 },
    company: { isRequired: true },
  }),
};
export const useFormHook = () =>
  useForm({
    FORM_CONFIG,
  });

# nested form

/* schemaForm.js */
import { useEffect, useRef } from "react";
import { useFormHook, Form } from "./hook.js";
import { InputField } from "./customInputField.js";

const schemaForm = () => {
  const { formRef, formId } = useFormHook();
  console.log(formRef);
  const submit = useCallback(() => {
    console.log(formRef.validateForm());
  }, []);
  return (
    <Form.Provider formRef={formRef}>
      <Form.Provider id="person">
        <InputField id="name" />
        <InputField id="age" />
        <InputField id="company" />
      </Form.Provider>
      <Button onClick={submit}>Submit</Button>
    </Form.Provider>
  );
};
  1. This is the image from console FormRef object

  1. This is the image from console after submitting form

# creating formArray hook config

/* hook.js */
import { newFormArray } from "react-form-validation-handler";
import { useForm } from "./form.js";

const FORM_CONFIG = {
  person: newFormArray({
    name: { isRequired: true },
    age: { min: 18, max: 16 },
    comapny: { isRequired: true },
  }),
};
export const useFormHook = () =>
  useForm({
    FORM_CONFIG,
  });

# FormArray

/* schemaForm.js */
import { useEffect, useRef } from "react";
import { useFormHook, Form } from "./hook.js";
import { InputField } from "./customInputField.js";

const schemaForm = () => {
  const { formRef, formId } = useFormHook();
  console.log(formRef);
  const submit = useCallback(() => {
    console.log(formRef.validateForm());
  }, []);
  return (
    <Form.Provider formRef={formRef}>
      <Form.Multiple id="person">
        {({ formRef: _formRef, form, formId, count, index }, arrayProps) => (
          <Form.Provider formRef={_formRef} key={formId}>
            <InputField id="name" />
            <InputField id="age" />
            <InputField id="company" />
            <button onClick={form.append}>> append</button>
            <button onClick={form.prepend}>prepend</button>
            <button onClick={form.delete}>delete</button>
            <button onClick={form.reset}>reset</button>
            <button onClick={form.clear}>clear</button>
            <button onClick={form.move}>move</button>
            <button onClick={form.swap}>swap</button>
            <button onClick={form.insert}>insert</button>
            <button onClick={form.clone}>clone</button>
            {console.log(arrayProps)}
          </Form.Provider>
        )}
      </Form.Multiple>
      <Button onClick={submit}>Submit</Button>
    </Form.Provider>
  );
};

Explanation

  • The useFormHook is used to obtain the form reference and form ID.
  • The Form.Provider wraps the entire form and provides context for form handling.
  • The Form.Multiple component is used to handle a dynamic array of form elements.
  • The InputField component is used for each form field within the dynamic array.
  • Various form manipulation buttons (append, prepend, delete,reset,clear,move,swap, insert,clone,etc.) are provided to showcase the dynamic form functionality.
  • The submit function is a callback that triggers form validation and logs the result.

Form Array methods

# Access FormRef Object using useformRef hook

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  console.log(formRef.getValues());
  console.log(formRef.getErrors());
};

# inputProps - <Object>

| Props | Default Value | type | description | | :------: | :-----------: | :------: | :---------------------------------------------------------------------: | | onChange | function | function | A callback function triggered when the value of the component changes. | | onBlur | function | function | A callback function triggered when the component loses focus (on blur). | | value | any | any | The current value of the input | | error | string | string | An error message associated with the input |

# Form config / InputConfig props - <Object>

| Props | Default Value | type | value | Description | | :----------------: | :-----------: | :------: | :------------------------------------------------------: | :----------------------------------------------------------------------------------------: | | isRequired | false | Boolean | true or false | A boolean indicating whether the field is required. Throws an error if the field is empty. | | optional | false | Boolean | true or false | A boolean indicating whether validation should occur only if the field has a value. | | min | null | number | 4 | A number indicating the minimum value required. | | max | null | number | 8 | A number indicating the maximum value required. | | maxLength | null | number | 7 | A number indicating the maximum characters allowed. | | minLength | null | number | 6 | A number indicating the minimum characters required. | | allowOnlyNumber | false | Boolean | true or false | A boolean indicating whether only numbers are allowed. | | allowValidNumber | false | number | true or false | A number indicating whether the entered number is valid or not. | | type | null | number | "email","number" | A string indicating the type of validation ("email", "number"). | | trim | null | Boolean | true or false | A boolean indicating whether spaces are allowed. | | pattern | null | regex | /\d+/ | A regular expression for custom pattern validation. | | message | null | object | {min: 'mimimum 8 characters required'} | An object providing custom error messages for different validation scenarios | | validator | null | function | (value) => ({error: value < 5 ? 'Error' : null,value}) | A function for custom validation logic. | | callback | null | function | ({value}) => {console.log('do something')} | A function called after validation. | | isValidateOnBlur | true | Boolean | true or false | A boolean indicating whether to validate the field on blur. | | isValidateOnChange | true | Boolean | true or false | A boolean indicating whether to validate the field on change | | vatidate | true | Boolean | true or false | A boolean indicating whether to set validation to true or false. | | default | '' | any | string or object or number | The default value for the field |

# getValues method

Get form values using getValues method

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  console.log(formRef.getValues());
};

# getErrors method

Get form errors using getErrors method

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  console.log(formRef.getErrors());
};

# clearForm method

clearForm will reset the form values to default

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  formRef.clearForm();
};

# resetForm method

resetForm will reset the form values to initialState

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  formRef.resetForm();
};

# getFormRef method

getFormRef will be used for nested form to access nested form ref

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  formRef.getFormRef(["person"]);
};

# getFormRefById method

getFormRefById similar to useFormRef for accessing formRef based on formId

/* hook.js */
const form = ({ formId }) => {
  const { formRef: nestedFormRef, formId } = formRef.getFormRefById(formId);
  console.log(nestedFormRef);
};

# renderForm method

renderForm will manually render the component

Note: By default components are not rendered on every change

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  formRef.renderForm();
};

# setFormValues method

setFormValues will be used for prefill form values

Note: By default only keys in the given object will be modified. If you want to reset and set new values, set second params to true

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  const IS_RESET_FORM = true;
  formRef.setFormValues(
    {
      name: "Person",
    },
    IS_RESET_FORM
  );
};

# validateForm method

validateForm will be used to validate the form

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  const onSubmit = () => {
    console.log(formRef.validateForm());
  };
};

# resetValues method

validateForm will be used to reset values based on keys

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  formRef.resetValues(["name"]);
};

# clearValues method

clearValues will be used to clear values based on keys

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  formRef.clearValues(["name"]);
};

# deleteFormConfig method

deleteFormConfig will be used to delete the formConfig

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  formRef.deleteFormConfig(["age"]);
};

# modifyFormConfig method

modifyFormConfig will be used to modify the formConfig

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  formRef.modifyFormConfig({
    age: {
      type: "number",
    },
  });
};

# resetFormConfig method

resetFormConfig will be used to reset the formConfig and set the newConfig

Note: This will remove the old config and set the new config

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  formRef.modifyFormConfig({
    age: {
      type: "number",
    },
  });
};

Form Array Props

# append method

append will add the new form after the target Form

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  const { append } = formRef.formArrayProps;

  const onAdd = () => {
    const targetFormId = __formId__;
    const values = [{ name: "steve" }];
    const noOfFormsToBeAdded = 2;
    append(targetFormId, values, noOfFormsToBeAdded);
  };
};

# prepend method

prepend will add the new form before the target Form

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  const { prepend } = formRef.formArrayProps;

  const onAddBefore = () => {
    const targetFormId = __formId__;
    const values = [{ name: "steve" }];
    const noOfFormsToBeAdded = 2;
    prepend(targetFormId, values, noOfFormsToBeAdded);
  };
};

# delete method

delete method will be used to delete the target form

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  const { prepend, delete: deleteForm } = formRef.formArrayProps;

  const onDeleteForm = () => {
    const targetFormId = [__formId1__, __formId2__];
    const values = [{ name: "steve" }];
    deleteForm(targetFormId);
  };
};

# clone method

clone method will be used to clone the target form

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  const { prepend, clone } = formRef.formArrayProps;

  const onCloneForm = () => {
    const sourceFormId = __formId1__;
    const noOfFormsToBeCloned = 2;
    clone(sourceFormId, noOfFormsToBeCloned);
  };
};

# clear method

clear method will be used to clear the target form

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  const { clear } = formRef.formArrayProps;

  const onClearForm = () => {
    const formIds = [__formId1__];
    clear(formIds);
  };
};

# reset method

reset method will be used to reset the target form

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  const { prepend, reset } = formRef.formArrayProps;

  const onResetForm = () => {
    const formIds = [__formId1__];
    reset(formIds);
  };
};

# move method

move method will be used to move the target form to particular index position

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  const { prepend, move } = formRef.formArrayProps;

  const onMoveForm = () => {
    const currentFormId = __formId1__;
    const targetFormId = __formId2__;
    move(currentFormId, targetFormId);
  };
};

# swap method

move method will be used to swap between two forms

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  const { prepend, swap } = formRef.formArrayProps;

  const onSwapForm = () => {
    const currentFormId = __formId1__;
    const targetFormId = __formId2__;
    forms(currentFormId, targetFormId);
  };
};

# insert method

insert method will be used to insert the new form on particular index

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  const { prepend, insert } = formRef.formArrayProps;

  const onInsertForm = () => {
    const targetFormId = __formId__;
    const values = [{ name: "steve" }];
    const noOfFormsToBeInserted = 2;
    insert(targetFormId, values, noOfFormsToBeInserted);
  };
};

# setFormRefArray method

setFormRefArray method will be used to change the order of the form and set the new form array

/* hook.js */
import { useFormRef } from "./hook.js";

const form = ({ formId }) => {
  const { formRef, formId } = useFormRef(formId);
  const { setFormRefArray } = formRef;

  const onSetFormRefArray = () => {
    setFormRefArray([formRef, formRef]);
  };
};

# Render Form

Note:

- set to true only if required. By default it will be false

- It will render component on every form change. Please use it only if required

/* hook.js */
import { newSchema } from "react-form-validation-handler";
import { useForm } from "./form.js";

const FORM_CONFIG = {
  person: newSchema({
    name: { isRequired: true },
    age: { min: 18, max: 16 },
    comapny: { isRequired: true },
  }),
};
const RENDER_FORM = true;
export const useFormHook = () =>
  useForm({
    FORM_CONFIG,
    renderForm: RENDER_FORM,
  });

# Don't reset form on unmount

Note:

- This will always maintain the form state even if you navigate from one page to another page

- If page is refreshed it will reset the form value

- It can be used for multiple step form

/* step_1.js */
import { useEffect, useRef } from "react";
import { useFormHook, Form } from "./hook.js";
import { InputField } from "./customInputField.js";

const Form = () => {
  const { formRef, formId } = useFormHook();
  const submit = useCallback(() => {
    if (formRef.validateForm().isValid) {
      // navigate("step_2", {
      //   formId,
      // });
    }
  }, []);
  return (
    <Form.Provider formRef={formRef} dontResetOnUnmount>
      <Form.Provider id="step_1">
        <Form.Provider id="person">
          <InputField id="name" />
          <InputField id="age" />
          <InputField id="company" />
        </Form.Provider>
      </Form.Provider>
      <Button onClick={submit}>Submit</Button>
    </Form.Provider>
  );
};
/* step_2.js */
import { useEffect, useRef } from "react";
import { useFormHook, Form } from "./hook.js";
import { InputField } from "./customInputField.js";

const Form = ({ formId }) => {
  const { formRef } = useFormRef(formId);
  const submit = useCallback(() => {
    console.log(formRef.validateForm());
  }, []);
  return (
    <Form.Provider formRef={formRef} dontResetOnUnmount>
      <Form.Provider id="step_2">
        <Form.Provider id="person">
          <InputField id="name" />
          <InputField id="age" />
          <InputField id="company" />
        </Form.Provider>
      </Form.Provider>
      <Button onClick={submit}>Submit</Button>
    </Form.Provider>
  );
};

# Form Controller

This will helps to controll multiple input props

/* step_1.js */
import { useEffect, useRef } from "react";
import { useFormHook, Form } from "./hook.js";
import { InputField } from "./customInputField.js";

const Form = () => {
  const { formRef, formId } = useFormHook();
  const submit = useCallback(() => {
    if (formRef.validateForm().isValid) {
      // navigate("step_2", {
      //   formId,
      // });
    }
  }, []);
  return (
    <Form.Provider formRef={formRef} dontResetOnUnmount>
      <Form.Provider id="step_1">
        <Form.Provider id="person">
          {({ values }) => (
            <>
              <InputField id="name" />
              <Form.Controller disabled={!values.name}>
                <InputField id="age" />
                <InputField id="company" />
              </Form.Controller>
            </>
          )}
        </Form.Provider>
      </Form.Provider>
      <Button onClick={submit}>Submit</Button>
    </Form.Provider>
  );
};

# Whether this package will support for react-native

Yes, this package will support for both react and react-native

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

License

Copyright (c) 2023-present Chrissie Fernando