rc-form-pure
TypeScript icon, indicating that this package has built-in type declarations

5.0.2 • Public • Published

rc-form-pure logo

RC FORM PURE

Declarative forms for React

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

type Description Input type Default
required check that value exist -
email check valid emails string -
number check value type any -
len validate an exact length of a field number -
min validate a min number number -
composeValidators compose your validators (custom and built-ins) function[] -

Package Sidebar

Install

npm i rc-form-pure

Weekly Downloads

101

Version

5.0.2

License

GPL-3.0-only

Unpacked Size

91.4 kB

Total Files

39

Last publish

Collaborators

  • mallchel