# ctx.form

Экземпляр формы Ant Design внутри текущего блока, используемый для чтения и записи полей формы, запуска валидации и отправки. Эквивалентен `ctx.blockModel?.form`, может использоваться напрямую в блоках, связанных с формами (Форма, Форма редактирования, подформа и т. д.).

## Примеры использования

| Сценарий | Описание |
|------|------|
| **JSField** | Чтение и запись других полей формы для реализации логики связей, вычислений или валидации на основе значений других полей. |
| **JSItem** | Чтение и запись полей в той же строке или других полей в элементах подтаблицы для реализации связей внутри таблицы. |
| **JSColumn** | Чтение значений текущей строки или связанных полей в столбце таблицы для рендеринга. |
| **Действия формы / Рабочий процесс** | Валидация перед отправкой, пакетное обновление полей, сброс формы и т. д. |

> Примечание: `ctx.form` доступен только в контекстах RunJS, связанных с блоками форм (Форма, Форма редактирования, подформа и т. д.). В сценариях, не связанных с формами (например, независимые блоки JSBlock или блоки таблиц), он может отсутствовать. Перед использованием рекомендуется проверять значение на существование: `ctx.form?.getFieldsValue()`.

## Определение типа

```ts
form: FormInstance<any>;
```

`FormInstance` — это тип экземпляра формы Ant Design. Основные методы приведены ниже.

## Основные методы

### Чтение значений формы

```ts
// Чтение значений всех зарегистрированных полей (по умолчанию только отрендеренных)
const values = ctx.form.getFieldsValue();

// Чтение значений всех полей (включая зарегистрированные, но не отрендеренные, например, скрытые или в свернутых секциях)
const allValues = ctx.form.getFieldsValue(true);

// Чтение значения одного поля
const email = ctx.form.getFieldValue('email');

// Чтение вложенных полей (например, в подтаблице)
const amount = ctx.form.getFieldValue(['orders', 0, 'amount']);
```

### Запись значений формы

```ts
// Пакетное обновление (часто используется для связей)
ctx.form.setFieldsValue({
  status: 'active',
  updatedAt: new Date(),
});

// Обновление одного поля
ctx.form.setFieldValue('remark', 'Обновленное примечание');
```

### Валидация и отправка

```ts
// Запуск валидации формы
await ctx.form.validateFields();

// Запуск отправки формы
ctx.form.submit();
```

### Сброс

```ts
// Сброс всех полей
ctx.form.resetFields();

// Сброс только определенных полей
ctx.form.resetFields(['status', 'remark']);
```

## Взаимосвязь с другими контекстами

### ctx.getValue / ctx.setValue

| Сценарий | Рекомендуемое использование |
|------|----------|
| **Чтение/запись текущего поля** | `ctx.getValue()` / `ctx.setValue(v)` |
| **Чтение/запись других полей** | `ctx.form.getFieldValue(name)` / `ctx.form.setFieldValue(name, v)` |

Внутри текущего JS-поля отдавайте приоритет `getValue`/`setValue` для работы с самим полем; используйте `ctx.form`, когда вам нужен доступ к другим полям.

### ctx.blockModel

| Требование | Рекомендуемое использование |
|------|----------|
| **Чтение/запись полей формы** | `ctx.form` (эквивалентно `ctx.blockModel?.form`, но удобнее) |
| **Доступ к родительскому блоку** | `ctx.blockModel` (содержит `collection`, `resource` и т. д.) |

### ctx.getVar('ctx.formValues')

Значения формы необходимо получать через `await ctx.getVar('ctx.formValues')`, они не предоставляются напрямую как `ctx.formValues`. В контексте формы предпочтительнее использовать `ctx.form.getFieldsValue()` для получения актуальных значений в реальном времени.

## Важные замечания

- `getFieldsValue()` по умолчанию возвращает только отрендеренные поля. Чтобы включить неотрендеренные поля (например, в свернутых секциях или скрытые правилами отображения), передайте `true`: `getFieldsValue(true)`.
- Пути для вложенных полей, таких как подтаблицы, представляют собой массивы, например, `['orders', 0, 'amount']`. Вы можете использовать `ctx.namePath`, чтобы получить путь текущего поля и сконструировать пути для других столбцов в той же строке.
- `validateFields()` выбрасывает объект ошибки, содержащий `errorFields` и другую информацию. Если валидация перед отправкой не удалась, вы можете использовать `ctx.exit()`, чтобы прервать последующие шаги.
- В асинхронных сценариях, таких как рабочие процессы или правила связей, `ctx.form` может быть еще не готов. Рекомендуется использовать опциональную цепочку или проверку на null.

## Примеры

### Связь полей: отображение разного контента в зависимости от типа

```ts
const type = ctx.form.getFieldValue('type');
if (type === 'vip') {
  ctx.form.setFieldsValue({ discount: 0.8 });
} else {
  ctx.form.setFieldsValue({ discount: 1 });
}
```

### Расчет текущего поля на основе других полей

```ts
const quantity = ctx.form.getFieldValue('quantity') ?? 0;
const price = ctx.form.getFieldValue('price') ?? 0;
ctx.setValue(quantity * price);
```

### Чтение/запись других столбцов в той же строке подтаблицы

```ts
// ctx.namePath — это путь текущего поля в форме, например, ['orders', 0, 'amount']
// Чтение 'status' в той же строке: ['orders', 0, 'status']
const rowIndex = ctx.namePath?.[1];
const status = ctx.form.getFieldValue(['orders', rowIndex, 'status']);
```

### Валидация перед отправкой

```ts
try {
  await ctx.form.validateFields();
  // Валидация пройдена, продолжаем логику отправки
} catch (e) {
  ctx.message.error('Пожалуйста, проверьте правильность заполнения формы');
  ctx.exit();
}
```

### Отправка после подтверждения

```ts
const confirmed = await ctx.modal.confirm({
  title: 'Подтверждение отправки',
  content: 'После отправки данные нельзя будет изменить. Продолжить?',
  okText: 'Подтвердить',
  cancelText: 'Отмена',
});
if (confirmed) {
  await ctx.form.validateFields();
  ctx.form.submit();
} else {
  ctx.exit(); // Прервать, если пользователь отменил действие
}
```

## Связанные разделы

- [ctx.getValue()](./get-value.md) / [ctx.setValue()](./set-value.md): Чтение и запись значения текущего поля.
- [ctx.blockModel](./block-model.md): Модель родительского блока; `ctx.form` эквивалентен `ctx.blockModel?.form`.
- [ctx.modal](./modal.md): Диалоговые окна подтверждения, часто используются вместе с `ctx.form.validateFields()` и `ctx.form.submit()`.
- [ctx.exit()](./exit.md): Прерывание процесса при ошибке валидации или отмене пользователем.
- `ctx.namePath`: Путь (массив) текущего поля в форме, используется для формирования имен в `getFieldValue` / `setFieldValue` для вложенных полей.