5.2.0 • Published 2 days ago

brief-form v5.2.0

Weekly downloads
-
License
MIT
Repository
github
Last release
2 days ago

brief-form

brief-form is a small React based form management tool. The main package API is useFormData hook which provides all necessary form data and service methods. It provides approach to manage form data but it's not bound to any particular UI implementation, so library can be used in web React apps or in the React Native applications.

Quick usage example

import React, { memo } from 'react'
import { FormProvider, useFormData } from 'brief-form'

type MyForm = {
  age: number
  name: string
  happy: boolean
}

const InitialValue = {
  age: 37,
  name: 'Andrey',
  happy: true
}

export const SomeFormComponent = memo(() => {
  const {
    isDirty,  // form value was changed
    isValid,  // form is valid
    validate, // method for form validation
    reset,    // reset form state
    Field,    // Field component to render UI input
    Form,     // Form component
    config    // form configuration object
  } = useFormData<MyForm>()

  return <FormProvider fieldRenderer={FieldRenderer}>
    <Form config={config}>
      <Field
        required
        name="name"
        label="Name"
        input={TextInput}
        validator={(v) => (v.length < 3 ? 'Name too short' : undefined)}
        inputProps={{}}
      />
      <Field 
        name="age" 
        label="Age" 
        input={NumberInput} 
        inputProps={{ type: 'integer' }} 
      />
      <Field 
        name="happy" 
        label="Happy?" 
        input={CheckBoxInput} 
        inputProps={{}} 
      />
    </Form>
  </FormProvider>
})

Let's dig into more details!

Form

Form is a container component holding all UI fields. The only required parameter is config. It's value returned from useFormData hook. As were mentioned before, library doesn't contain any UI implementations, so we should explicitly define which UI component should render form UI field (basically it should render label, input and error). We can do it through fieldRenderer Form parameter to set renderer individually for each form. Or we can use FormProvider component and set up this renderer globally for all nested forms.

<Form config={config} fieldRenderer={UIField}>
</Form>

FormProvider

FormProvider gives us ability to perform global form setup.

fieldRenderer parameter accepts React component to be used for rendering form UI field.

crashIfRequiredFieldDoesNotHaveValidator defines whether form should crash if it contains any fields marked as required but not providing validator function. In most cases it helps more quickly find required inputs without validators during development. Basically required field property just marks fields as required (e.g. field renderer can draw asterisk near label for these fields). Validator function contains logic defining whether field "empty" or "filled". For example we can think about integer input as empty if its value is 0, but for more complex inputs things may be more complex and ambiguous. That's why we need custom validator here.

We would recommend always use FormProvider component to reduce amount of boilerplate code.

useFormData

This hook is the main library API.

  const formData = useFormData<MyFormType>(initialData, initialErrors)

It expects generic parameter (MyFormType) describing form value shape and two arguments - initial form data (required) and initial form errors (optional).

Let's take a look at what formData contains:

NameTypeDescription
isDirtybooleanform value was changed
isValidbooleanform is valid
validate(withFormUpdate = false) => { [key: string]: string }method for form validation. It returns errors dictionary (if any) or empty object. This function accepts optional boolean parameter withFormUpdate. It's false by default. If this parameter is true all errored fields will be highlighted after function execution. We would suggest to use it on form submit to show user all input problems.
reset(newInitialValue, newErrors) => voidreset form state, optionally new initial value and errors can be provided. isDirty flag is set to false. isValid is set dependingly on newErrors parameter.
Fieldcomponent to render UI input. It accepts form data field name, input renderer, validator etc. Look for detailed description in the sections below.
FormForm container component

We highly recommend to use Form and Field components returned from this hook, as they are already bound to form type passed to hook.

Field

This component is the main form field data management piece. Its parameters are listed below:

NameRequiredTypeDescription
nametrueOne of the form keysdefines which form data field this UI field should handle
requiredbooleanDefines whether this field is required
errorstringAllows to explicitly set form field error
labelReactNodeDefines input label
inputtruecomponent implementing FormInputProps<V, P>Input component which actually should handle user input. See sections below for more details.
validator(v,f) => string \| undefinedOptional validator function. Accepts field and form values as arguments. Returns undefined if field is valid, otherwise error string should be returned.
inputPropstrueInput specific props dictionaryEach field input accepts FormInputProps, but also can have own specific properties. It's a right place to pass it.

Field input component

It were mentioned above, input should implement FormInputProps<V, P> interface where V is a input value type and P is a input specific properties. FormInputProps interface described below:

export interface FormInputProps<V, P> {
  // input specific properties
  opts: P                                       
  // input value
  value: V                                      
  // value change handler (input specific error can be passed as a second argument)
  onChange: (value: V, error?: string) => void  
  // input error
  error?: string
  // whether input is required
  required?: boolean
}

As we can see here, each form input component is given all basic necessarry data to properly display its state and handle value updates.

Let's imagine we want to implement check box list input for our form:

import { ReactNode } from 'react'
import { FormInputProps } from 'brief-form'

import { Wrapper } from './styles'

export type CheckBoxListValue = { [key: string]: boolean }

export type CheckBoxLabels = { [key: keyof CheckBoxListValue]: ReactNode }

export type CheckBoxListOpts = {
  labels: CheckBoxLabels
  disabled?: boolean
}

export interface CheckBoxListProps extends FormInputProps<CheckBoxListValue, CheckBoxListOpts> {}

export const CheckBoxList: FC<CheckBoxListProps> = memo((props) => {
  const {
    value, // CheckBoxListValue
    onChange, // (value: CheckBoxListValue, error?: string) => void
    opts: { labels, disabled } // CheckBoxListOpts
  } = props

  return (
    <>
      ...
    </>
  )
})
Footer

P.S

Any suggestions are welcomed. Feel free to contact me by email andrey.barkanov@gmail.com.

5.2.0

2 days ago

5.1.10

2 days ago

5.1.9

15 days ago

5.1.8

3 months ago

5.1.7

3 months ago

5.1.6

3 months ago

5.1.5

3 months ago

5.1.4

3 months ago

5.1.3

3 months ago

5.1.2

3 months ago

5.1.1

3 months ago

5.1.0

3 months ago

4.0.1

8 months ago

4.0.0

8 months ago

5.0.6

6 months ago

5.0.5

7 months ago

5.0.4

7 months ago

5.0.3

7 months ago

5.0.2

7 months ago

5.0.1

7 months ago

5.0.0

7 months ago

4.2.10

7 months ago

4.2.11

7 months ago

3.0.1

8 months ago

3.0.0

10 months ago

4.2.3

7 months ago

4.2.2

8 months ago

4.2.5

7 months ago

4.2.4

7 months ago

4.2.1

8 months ago

4.2.0

8 months ago

4.2.7

7 months ago

4.2.6

7 months ago

4.2.9

7 months ago

4.2.8

7 months ago

4.1.3

8 months ago

4.1.0

8 months ago

4.1.2

8 months ago

4.1.1

8 months ago

2.1.4

12 months ago

2.1.2

1 year ago

2.1.1

1 year ago

2.1.3

1 year ago

2.0.0

1 year ago

2.1.0

1 year ago

1.1.9

1 year ago

1.1.8

1 year ago

1.1.7

1 year ago

1.1.6

2 years ago

1.1.5

2 years ago

1.1.4

2 years ago

1.0.2

2 years ago

1.0.18

2 years ago

1.0.1

2 years ago

1.0.17

2 years ago

1.0.0

2 years ago

1.0.16

2 years ago

1.0.9

2 years ago

1.0.8

2 years ago

1.0.7

2 years ago

1.0.6

2 years ago

1.0.5

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.1.1

2 years ago

1.1.0

2 years ago

1.1.3

2 years ago

1.1.2

2 years ago

1.0.11

2 years ago

1.0.10

2 years ago

1.0.15

2 years ago

1.0.14

2 years ago

1.0.13

2 years ago

1.0.12

2 years ago

0.0.41

2 years ago

0.0.42

2 years ago

0.0.40

2 years ago

0.0.39

3 years ago

0.0.38

3 years ago

0.0.37

3 years ago

0.0.34

3 years ago

0.0.35

3 years ago

0.0.36

3 years ago

0.0.33

3 years ago

0.0.32

3 years ago

0.0.30

3 years ago

0.0.31

3 years ago

0.0.28

3 years ago

0.0.29

3 years ago

0.0.25

3 years ago

0.0.26

3 years ago

0.0.27

3 years ago

0.0.24

3 years ago

0.0.23

3 years ago

0.0.21

3 years ago

0.0.20

3 years ago

0.0.19

3 years ago

0.0.18

3 years ago

0.0.17

3 years ago

0.0.16

3 years ago

0.0.15

3 years ago

0.0.14

3 years ago

0.0.13

3 years ago

0.0.12

3 years ago

0.0.11

3 years ago

0.0.10

3 years ago

0.0.9

3 years ago

0.0.8

3 years ago

0.0.7

3 years ago

0.0.6

3 years ago

0.0.5

3 years ago

0.0.4

3 years ago

0.0.3

3 years ago

0.0.2

3 years ago

0.0.1

3 years ago