5.0.2 • Published 3 months ago

rc-form-pure v5.0.2

Weekly downloads
393
License
GPL-3.0-only
Repository
github
Last release
3 months ago

rc-form-pure

Performant, flexible, lightweight and abstract library for creating React forms

Features

  • The convenience of handling dependent fields
  • Configuring fields at the FormItem level, as well as at the level FormBuilder via extraFieldsProps
  • Out of the box, FormItem is a pure component (better performance for large forms)
  • Independent from state managers
  • Can be used in React Native
  • Small size
  • Zero dependencies
  • Written on the Typescripts

Bundle size (and comparison with similar other) - https://bundlephobia.com/result?p=rc-form-pure

Demo

Install

npm i rc-form-pure

Usage

Example

import React from 'react';
import { FormBuilder, FormItem, Validators, ComponentPropTypes, IFieldsToSubmit } from 'rc-form-pure';

const TextField: ComponentPropTypes<{}> = props => {
  const { name, onChange, error, value } = props;

  return (
    <>
      <label>{name}</label>
      <input value={value} onChange={e => onChange(e.target.value)} />
      {error}
    </>
  );
};

const TestFrom = () => {
  const onSubmit = (formData: IFieldsToSubmit, fieldWithError: IFieldsToSubmit | null) => {
    console.log('onSubmit', formData, fieldWithError);
  };

  return (
    <FormBuilder onSubmit={onSubmit} withForm>
      <FormItem name="country" component={TextField} />

      <FormItem
        name="required-field"
        validate={Validators.required}
        errorMessage={'Please fill this field'}
        component={TextField}
      />

      <button>onSubmit</button>
    </FormBuilder>
  );
};

export default TestFrom;

FormBuilder Props

type FormBuilderPropTypes = {
  // Object schema: { currency: 'Your error text' }
  errors?: Record<string, string | null>;

  // Determines if the form tag will be in the DOM
  withForm?: boolean;

  // You can specify a function that returns a custom wrapper of form
  renderForm?: Function;

  // Submit function will get values and errors
  onSubmit: (values: IFieldsToSubmit, fieldsWithError: FieldsWithErrorType) => Promise<any> | void;

  // The top level listener for fields changes Function(allFields, updatedFields) or { [nameField]: (specificfield, allFields) => {}
  onChangeFields?: OnChangeFieldsType;

  // Validate after onBlur or after every change can be overridden in the FormItem props
  validateOnBlur?: boolean;

  // initial values
  initialValues?: Record<FieldNameType, any>;

  // extra props will be mixed with service IField properties
  extraFieldsProps?: Record<FieldNameType, any>;
  or;
  // Pass the base config to all fields
  extraFieldsProps?: Record<'$all', any>;
};

FormItem Props

type FormItemTypes = {
  // The field name in the FormBuilder state
  name: string;

  // Your component
  component?: ComponentPropTypes<any>;

  // The formatter will be called before being saved to the FormBuilder state
  formatter?: (value: any) => any;

  // Override global validateOnBlur for some field
  validateOnBlur?: boolean;

  // function type of (value: any, message: string | string[]) => null | string | string[]
  validate?: ValidateType;

  // The error message that will appear when validation fails
  errorMessage?: ErrorMessageType;

  // Override global initialValue
  initialValue?: any;
};

There are several built-in Validators for convenience

FormItem nested fields

You can nest your fields by easily wrapping FromItem components in each other

<FormItem name="my-nested-group">
  <FormItem name="age" component={TextField} />
  <FormItem name="country" component={TextField} />
</FormItem>

The FormBuilder state will have the following properties:

my - nested - group.age;
my - nested - group.country;

API

useFormApi

import { useFormApi } from 'rc-form-pure';

const {
  setFields,
  setFieldsValue,
  getFieldsValue,
  useWatchFields,
  useWatchValue,
  useInitialValues,
  useSubmit,
} = useFormApi();

// also you can import each hook independently (without useFormApi)
import { useWatchFields, useWatchValue, useInitialValues, useSubmit } from 'rc-form-pure';

setFieldsValue

(updates: Record<string, any>, options: { changeEvent: boolean }) => void;
// changeEvent option has "true" value by default
// setting a new value:
setFieldsValue({ [FIELDS_CONFIG.currency.key]: '$' });

setFields

(updates: Record<string, Partial<IField>>, options: { changeEvent: boolean }) => void;
// changeEvent option has "true" value by default
// resetting value and error:
setFields({
  [FIELDS_CONFIG.currency.key]: { value: '', error: null },
});

getFieldsValue

(fieldKey?: string) => IFieldsToSubmit | PickPropType<IField, 'value'>

// get all values:
const formFields: IFieldsToSubmit = getFieldsValue();

// get the value of a specific field:
const formFields: any = getFieldsValue(FIELDS_CONFIG.currency.key);

useWatchValue

(fieldKey?: string) => Record<string, any> | any

// watch a specific field value
const countryValue = useWatchValue('country');

// watch a specific field value with a default value
const countryValue = useWatchValue('country', 'Russia');

// watch all values
const allValues = useWatchValue();

useInitialValues

(fieldKey?: string) => any;

// get a specific field initial value from FormBuilder
const countryInitialValue = useInitialValues('country');

// for example, you can use with useWatchValue
const countryValue = useWatchValue('country', countryInitialValue);

useWatchFields

(fieldKey?: string) => Array<specificField, allFields> | Array<allFields, updatedFields>

// invoked when a specific field changes
const [countryField, allFields] = useWatchFields('country');

// invoked on any fields changes
const [allFields, updatedFields] = useWatchFields();

useSubmit

(event?: any) => void

const { onSubmit } = useSubmit();

// call it when you want, and it will trigger onSubmit event on the FormBuilder
onSubmit();

formRef

You can get the form external API on the form level via useRef

const formRef = useRef<FormBuilder>(null);

formRef.current?.setFields;
formRef.current?.setFieldsValue;
formRef.current?.getFields;
formRef.current?.getFieldsValue;

Types

ComponentPropTypes

Extend your component prop types

type MyExtraPropTypes = {
  extraProps: boolean;
  disabled: boolean;
  globalFormReadonly: boolean;
};
const TextField: ComponentPropTypes<MyExtraPropTypes> = props => {
  const { name, error, onChange, disabled, globalFormReadonly, value } = props;

  return (
    <div>
      <label>{name}</label>
      <input disabled={disabled || globalFormReadonly} value={value} onChange={e => onChange(e.target.value)} />
      {error}
    </div>
  );
};

ErrorsType

FormBuilder "errors" prop type

const serverErrors: ErrorsType = {
  firstName: 'asd',
};

const [errors, setServerErrors] = useState<ErrorsType>(null);

IFieldsToSubmit

FormBuilder value types

const onSubmit = (formData: IFieldsToSubmit, fieldWithError: IFieldsToSubmit | null) => {
  console.log('onSubmit', formData, fieldWithError);
};

OnChangeFieldsType

FormBuilder "onChangeFields" prop type

const onChangeFields: OnChangeFieldsType = (allFields, updatedFields) => {
  console.log('onChangeFields', allFields, updatedFields);
};

const onChangeFields: OnChangeFieldsType = {
  country: (field, allFields) => {
    console.log('onChangeFields', field, allFields);
  },
};

Built-in Validators

typeDescriptionInput typeDefault
requiredcheck that value exist-
emailcheck valid emailsstring-
numbercheck value typeany-
lenvalidate an exact length of a fieldnumber-
minvalidate a min numbernumber-
composeValidatorscompose your validators (custom and built-ins)function[]-
5.0.2

3 months ago

5.0.1

4 months ago

5.0.0

2 years ago

4.0.0

3 years ago

3.3.1

3 years ago

3.3.0

3 years ago

3.2.0

3 years ago

3.1.17

3 years ago

3.1.16

3 years ago

3.1.15

3 years ago

3.1.14

3 years ago

3.1.13

4 years ago

3.1.12

4 years ago

3.1.11

4 years ago

3.1.10

4 years ago

3.1.9

4 years ago

3.1.8

4 years ago

3.1.7

4 years ago

3.1.6

4 years ago

3.1.5

4 years ago

3.1.4

4 years ago

3.1.3

4 years ago

3.1.2

4 years ago

3.1.1

4 years ago

3.1.0

4 years ago

3.0.9

4 years ago

3.0.8

4 years ago

3.0.7

4 years ago

3.0.5

4 years ago

3.0.4

4 years ago

3.0.3

4 years ago

3.0.2

4 years ago

3.0.1

4 years ago

3.0.0

4 years ago

2.1.9

4 years ago

2.1.8

4 years ago

2.1.6

4 years ago

2.1.7

4 years ago

2.1.5

4 years ago

2.1.4

4 years ago

2.1.3

4 years ago

2.1.2

4 years ago

2.1.1

4 years ago

2.1.0

4 years ago

2.0.8

4 years ago

2.0.7

4 years ago

2.0.6

4 years ago

2.0.5

4 years ago

2.0.4

4 years ago

2.0.3

4 years ago

2.0.2

4 years ago

2.0.1

4 years ago

2.0.0

4 years ago

1.3.3

5 years ago

1.3.2

5 years ago

1.3.1

5 years ago

1.3.0

5 years ago

1.3.0-0

5 years ago

1.2.1

6 years ago

1.2.0

6 years ago

1.1.0

6 years ago

1.0.8-7

6 years ago

1.0.8-6

6 years ago

1.0.8-5

6 years ago

1.0.8-4

6 years ago

1.0.8-3

6 years ago

1.0.8-2

6 years ago

1.0.8-1

6 years ago

1.0.8-0

6 years ago

1.0.7

6 years ago

1.0.6

6 years ago

1.0.5

6 years ago

1.0.4

6 years ago

1.0.3

6 years ago

1.0.2

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago

0.4.9

6 years ago

0.4.8

6 years ago

0.4.7

6 years ago

0.4.6

6 years ago

0.4.5

6 years ago

0.4.4

6 years ago

0.4.2

6 years ago

0.4.1

6 years ago

0.4.0

6 years ago

0.3.1

6 years ago

0.3.0

6 years ago

0.2.1

6 years ago

0.2.0

6 years ago

0.1.1

6 years ago

0.1.0

6 years ago