0.8.0 • Published 1 month ago

react-modular-forms v0.8.0

Weekly downloads
-
License
-
Repository
-
Last release
1 month ago

react-modulr-forms

This library aims at solving the issues of complex forms in an extensible way. It allows multiple types of validation and arranging forms inn any way you see fit. It allows plugin any external library into it's validation process to prevent form submission or display errors in a unified manner.

Components

ModularForm

The ModularForm component will wrap our FormField elements, it simply has an id prop that will be referenced by each field. It can wrap its elements but any element outside of the form will also be registered as long as it holds the correct formId.

import { ModularForm } from 'react-modular-forms';
const formId = 'my-form';
<ModularForm id={formId}>

</ModularForm>

ModularFormField

The ModularFormField is used to render any form field element. It must have a formId prop to reference it's parent form and either a name or an id prop.

Every native HTML form field element should be supported out of the box.

const formId = 'my-form';
<ModularForm id={formId}>
    
    <ModularFormField formId={formId} name="email" type="email" />

</ModularForm>

Validation

Validation is implemented by providing the validation prop to ModularFormField components.

export type ValidationType = {
  required?: boolean;
  /**
   * If field valued doesn't match RegExp in negativeRegExps the error string will be displayed
   */
  negativeRegExps?: { [error: string]: RegExp };
  /**
   * If field valued  matches RegExp in positiveRegExps the error string will be displayed
   */
  positiveRegExps?: { [error: string]: RegExp };
  /**
   * A custom validator function, should return an error string if value isn't valid or null if it is
   */
  validator?: (value: any) => string | null;
  validateOnBlur?: boolean;
  /**
   * The group prop allows the form to validate multiple fields
   */
  group?: string;
  /**
   * groupMin tells the form how many fields in the group must be valid for the form to be submitted
   */
  groupMin?: number;
};

Registering new components with registerType

The registerType helper allows you to register external libraries or custom components as form fields. If you for example wanted to register react-select as component:

import React from 'react';
import Select from 'react-select';

const ReactSelectWrapper = ({ name, value: _value, onChange, componentRef,...props }: FieldComponentProps) => {
    const [value, setValue] = useState<any>(_value);

    useEffect(() => {
        componentRef.current = value;
    }, []);
    return (
        <Select
            name={Array.isArray(name) ? name.join('.') : name}
            value={value}
            onChange={(option) => {
                setValue(option);
                componentRef.current = option.value;
                onChange(null, option.value);
                return option;
            }}
            {...props}
        />
    );
};

registerType('react-select', {
    Component: ReactSelectWrapper,
    getValue: (ref: RefObject<string | undefined>) => ref.current
});

When registering custom form field types, you should ensure events methods are handled on the component for validation to be properly handled. You can use the componentRef or the setComponentRef props to give the library something to access the field's value. This ref will be passed to the getValue function that will be used to validate the field.

{
  onChange?: (e: unknown, ...any: any[]) => void;
  onBlur?: (e: React.SyntheticEvent) => void;
  onFocus?: (e: React.SyntheticEvent) => void;
  componentRef: React.MutableRefObject<any>;
  setComponentRef: (value: any) => RefObject<any>;
}

Using registerType to register complex types without adding validation hooks

If you wish to create ModularFormField types without adding validation hook you can use the isStatic boolean option of the registerType function. This will prevent the logic from being implemented twice if the components referenced are already ModularFormFields. This will allow the creation of complex fields with ease or even group multiple fields into a single component.

registerType('address-fields', {
    Component: ({ formId, prefix }: FieldComponentProps & { prefix: string}) => {
        return <>
            <ModularFormField formId={formId} type="text" name={`${prefix}address`} label="Address" validation={{required: true}} />
            <ModularFormField formId={formId} type="text" name={`${prefix}city`} label="City" validation={{required: true}}  />
            <ModularFormField formId={formId} type="tel" name={`${prefix}zipcode`} label="Zipcode" validation={{required: true}}  />
            <ModularFormField formId={formId} type="text" name={`${prefix}country`} label="Country" validation={{required: true}}  />
        </>
    },
    isStatic: true
});
0.8.0

1 month ago

0.7.0

3 months ago

0.6.0

4 months ago

0.5.3

7 months ago

0.5.0

7 months ago

0.5.2

7 months ago

0.5.1

7 months ago

0.4.15

8 months ago

0.4.16

8 months ago

0.4.13

10 months ago

0.4.14

9 months ago

0.4.12

12 months ago

0.4.9

1 year ago

0.4.8

1 year ago

0.4.10

1 year ago

0.4.11

1 year ago

0.3.0

1 year ago

0.2.0

1 year ago

0.4.5

1 year ago

0.4.4

1 year ago

0.4.7

1 year ago

0.4.6

1 year ago

0.4.1

1 year ago

0.4.0

1 year ago

0.4.3

1 year ago

0.4.2

1 year ago

0.0.30

1 year ago

0.0.31

1 year ago

0.0.32

1 year ago

0.1.0

1 year ago

0.0.20

2 years ago

0.0.21

2 years ago

0.0.22

2 years ago

0.0.23

2 years ago

0.0.24

2 years ago

0.0.25

2 years ago

0.0.15

2 years ago

0.0.16

2 years ago

0.0.17

2 years ago

0.0.18

2 years ago

0.0.19

2 years ago

0.0.10

2 years ago

0.0.11

2 years ago

0.0.12

2 years ago

0.0.13

2 years ago

0.0.14

2 years ago

0.0.26

2 years ago

0.0.27

2 years ago

0.0.28

2 years ago

0.0.29

2 years ago

0.0.9

2 years ago

0.0.8

2 years ago

0.0.5

2 years ago

0.0.6

2 years ago

0.0.4

2 years ago

0.0.3

2 years ago

0.0.2

2 years ago

0.0.1

2 years ago