npm package: @n3/react-form-builder
Description: React component for building forms by schema
Author: Vadim Taits
Latest version: 0.8.1

# @n3/react-form-builder

React-компонент для построения форм по схеме. Для работы с состоянием используется `final-form`.

## Установка

```
npm install @n3/react-form-builder
```

или

```
yarn add @n3/react-form-builder
```

### Использование

```javascript
import { Form } from '@n3/react-form-builder';

// ...

<Form
  onSubmit={onSubmit}
  initialValues={initialValues}
  schema={schema}
  getFieldSchema={getFieldSchema}
  getFieldType={getFieldType}
  errorsPath={errorsPath}
  mapErrors={mapErrors}
  formProps={formProps}
  renderError={renderError}
  renderWarning={renderWarning}
  renderButtons={renderButtons}
  layoutComponent={layoutComponent}
  onFieldChange={onFieldChange}
  {...otherProps}
/>
```

### Props

- `onSubmit` - обязательное, функция, аналогична `react-final-form`, отличия:

  - первым аргументом принимает сериализованные значения формы, а вторым - оригинальные значения `final-form`;

  - ошибки могут быть возвращены в объекте, а могут возвразаться через `throw`;

- `onFieldChange` - необязательное, функция срабатывает при изменении значения поля, аргументы:

  - `value` - значение поля;
  - `prevValue` - предыдущее значение поля;
  - `path` - путь до поля;
  - `form` - экземпляр [формы final-form](https://final-form.org/docs/final-form/types/FormApi);

- `initialValues` - необязательное, объект, аналогичен `react-final-form`, но перед передачей в форму обрабатывается полями схемы;

- `schema` - обязательное, массив, содержит элементы, по каждому из которых будет получена схема поля с помощью функции `getFieldSchema`;

- `parents` - обязательное, массив, элементами являются объекты с параметрами:

  - `name` - необязательное, строка. Для корневого элемента (формы) отсутствует, для вложенных полей - имя группирующего поля;

  - `values` - обязательное, объект, значения текущего группируюшего поля;

- `getFieldSchema` - необязательное, функция маппинга элементов `schema` в схему поля;

- `getFieldType` - обязательное, функция получения типа поля по схеме поля, должна возвращать объект формата:

  - `createGetFieldSchema` - необязательное, функция для переопределения `getFieldSchema` на уровне компонента поля и мапперов, принимает аргументы:

    1. `fieldSchema` - схема поля;
    2. `getFieldSchema` - `getFieldSchema` родительского элемента или формы;
    3. `getFieldType` - из компонента `Form`;
    4. `values` - объект значений формы на этапе рендера/сериализации или объект необработанных значений на этапе парсинга;
    5. `phase` - `'parse'`, `'serialize'` или `'render'`;
    6. `parents` - смотри выше;

  - `component` - обязательное, react-компонент поля формы. Принимает в качестве props схему поля, а также дополнительные `props`:

    - `getFieldSchema` - обязательное, смотри выше;

    - `getFieldType` - обязательное, из компонента `Form`;

    - `onFieldChange` - обязательное, функция из компоента `Form`, но без аргумента `change`;

    - `renderField` - обязательное, функция рендера дочернего компонента по имени, аргументы:

      1. `name` - имя вложенного поля;
      2. `member` - префекс имени вложенного поля (для массивов и групп полей);

  - `valueMapper` - необязательное, функция, определяющая, как поле будет передваться в `onSubmit`, аргументы:
    1. `values` - объект значений формы;
    2. `fieldSchema` - схема поля;
    3. `getFieldSchema` - смотри выше;
    4. `getFieldType` - смотри выше;
    5. `parents` - смотри выше;

    должна возвращать обеъкт значений для отправки. По умолчанию отправляет только значение из `values` по ключу `"name"` из схемы формы;

  - `valueParser` - необязательное, функция, определяющая, как поле будет определять своё значение для инициализации, аргументы:
    1. `initialValues` - из компонента `Form`;
    2. `fieldSchema` - схема поля;
    3. `getFieldSchema` - смотри выше;
    4. `getFieldType` - смотри выше;
    5. `parents` - смотри выше;

    должна возвращать обеъкт значений. По умолчанию возвращает только значение из `initialValues` по ключу `"name"` из схемы формы. Может быть асинхронной;

  - `errorsMapper` - необязательное, функция, определяющая, как поле будет переводить ошибки сабмита в свой формат, аргументы:
    1. `errors` - объект ошибок;
    2. `fieldSchema` - схема поля;
    3. `getFieldSchema` - смотри выше;
    4. `getFieldType` - смотри выше;
    5. `values` - значения полей формы после обработки;
    6. `rawValues` - значения полей формы;
    5. `parents` - смотри выше, в качестве значений использует сериализованные значения формы;

    должна возвращать обеъкт значений. По умолчанию возвращает только значение из `errors` по ключу `"name"` из схемы формы;

  - `memberMapper` - необязательное, функция, процессор схемы для случая, когда поле вложено в другое поле (например, оно находится внутри группы полей `FieldArray`):
    1. `member` - префикс имени поля;
    2. `fieldSchema` - схема поля;
    3. `getFieldSchema` - смотри выше;
    4. `getFieldType` - смотри выше;

    должна возвращать новую схему. По умолчанию возвращает `fieldSchema` с переопределённым `name`, равным `${member}.${fieldSchema.name}`;

- `errorsPath` - необязательное, строка, в случае ошибки отправки определяет путь до объекта ошибки, по умолчанию `"response.data"` (`axios`);
- `mapErrors` - необязательное, функция, в случае ошибки отправки обрабатывает объект ошибки перед вызовом `SubmissionError`, по умолчанию переделывает `non_field_errors` и `detail` в `_error`. Принимает аргументы:
  
  1. `errors` - оригинальный объект ошибок;

  2. `values` - значения полей формы после обработки;

  3. `rawValues` - значения полей формы;

- `getError` - необязательное, функция получения ошибки по объекту `error`. По умолчанию возвращает полностью `error`. Может быть использована для вывода ошибок и предупреждений;

- `getWarning` - необязательное, функция получения ошибки по объекту `error`. По умолчанию возвращает null. Может быть использована для вывода ошибок и предупреждений;

- `renderFields` - необязательное, функция рендера полей формы, принимает все render props `react-final-form`, а также дополнителное `renderField` для рендера поля по имени, пример использования:

  ```javascript
  renderFields={({
    submitting,
    renderField,
  }) => (
    <>
      <ul>
        <li>
          {renderField('input')}
        </li>

        <li>
          {renderField('requiredInput')}
        </li>

        <li>
          {renderField('select')}
        </li>

        <li>
          {renderField('date')}
        </li>
      </ul>

      {
        submitting && (
          <p>
            Submitting...
          </p>
        )
      }
    </>
  )}
  ```

- `renderError` - необязательное, функция, должна вернуть реакт-элемент ошибки формы. Первым аргументом принимает ошибку. По умолчанию отображает красный текст;

- `renderWarning` - необязательное, функция, должна вернуть реакт-элемент предупреждения формы. Первым аргументом принимает предупреждение. По умолчанию отображает тёмно-оранжевый текст;

- `renderButtons` - необязательное, функция, должна вернуть реакт-элемент кнопок формы. Первым аргументом принимает объект, содержащий функции `form` (экземпляр [формы final-form](https://final-form.org/docs/final-form/types/FormApi)) и функцию `handleSubmit` (смотри [react-final-form](https://final-form.org/docs/react-final-form/api/Form)). По умолчанию отображает submit-кнопку;

- `formProps` - необязательное, объект, дополнительные `props` компонента `<form>`, например, `noValidate`;

- `layoutComponent` - необязательное, react-компонент, кастомный лэйаут формы. Принимает `props`:
  - `formProps` - из компонента `Form`;
  - `formFields` - обязательное, react-элемент, блок полей формы;
  - `error` - необязательное, react-элемент, блок ошибок;
  - `warning` - необязательное, react-элемент, блок предупреждений;
  - `buttons` - необязательное, react-элемент, блок кнопок;
  - `handleSubmit` - смотри [react-final-form](https://final-form.org/docs/react-final-form/api/Form).

### Утилиты

#### ARRAY_ERROR

```javascript
import { ARRAY_ERROR } from '@n3/react-form-builder';
```

Смотри [final-form](https://github.com/final-form/final-form#array_error-string)

#### FORM_ERROR

```javascript
import { FORM_ERROR } from '@n3/react-form-builder';
```

Смотри [final-form](https://github.com/final-form/final-form#form_error-string)

#### useForm

```javascript
import { useForm } from '@n3/react-form-builder';
```

Смотри [react-final-form](https://github.com/final-form/react-final-form#useform)

#### useFormState

```javascript
import { useFormState } from '@n3/react-form-builder';
```

Смотри [react-final-form](https://github.com/final-form/react-final-form#useformstate)

#### useField

```javascript
import { useField } from '@n3/react-form-builder';

const Field = ({
  name,
  onFieldChange,
}) => {
  const {
    input,
    meta,
  } = useField(name, {
    onFieldChange,
  });

  // ...
}
```

Аналогично [react-final-form](https://github.com/final-form/react-final-form#usefield), но в объект параметров должно принимать `onFieldChange`, который передаётся полю через `props`.

Аргументы `onFieldChange`:

1. `nextValue` - значение поля после изменения;
2. `prevValue` - значение поля до изменения;
3. `name` - имя поля;
4. `form` - экземпляр `final-form`.

#### useFieldArray

```
import { useFieldArray } from '@n3/react-form-builder';
```

Смотри [react-final-form-arrays](https://github.com/final-form/react-final-form-arrays#usefieldarray)

#### useRepeat

Хук для создания повторяющихся групп полей на основе `useFieldArray`.

```javascript
import { useRepeat } from '@n3/react-form-builder';

const RepeatField = ({
  name,
  initialValues,
  required,
}) => {
  const {
    fields,
    meta,
    handleAdd,
    handleRemove,
  } = useRepeat(name, {
    onFieldChange,
  });

  const removeByIndex = (index) => {
    handleRemove(index);
  };

  // ...
}
```

Аналогично `useFieldArray`, но добавляются хендлеры добавления и удаления групп полей.

- `handleAdd` - функция, при вызове добавляет новую группу полей со значениями `initialValues`;

- `handleRemove` - функция, удаляет группу полей по выбранному индексу. Если группа была единственная, а также `required` = true, то добавляет новую группу полей с `initialValues`.


#### useFormSchemaState

```javascript
import { useFormSchemaState } from '@n3/react-form-builder';
```

Смотри [@vtaits/react-final-form-schema](https://www.npmjs.com/package/@vtaits/react-final-form-schema#usefieldarray)

#### Утилиты

- `serialize`
- `parse`
- `mapFieldErrors`
- `validateBeforeSubmit`

Смотри [@vtaits/form-schema](https://www.npmjs.com/package/@vtaits/form-schema)