Зависимые поля

В Ant Design зависимые поля (dependent fields) — это элементы формы, значение которых изменяется в зависимости от состояния или значения других полей. Такая логика особенно полезна при создании динамических форм, где пользовательский ввод на одном шаге влияет на доступные варианты или поведение других элементов.

В библиотеке Ant Design ключевым инструментом для реализации зависимых полей является компонент Form совместно с методами Form.Item и Form.useForm.


Использование Form.useForm

Для управления зависимостями полей необходимо создать экземпляр формы:

import { Form, Input, Select, Button } from 'antd';

const [form] = Form.useForm();

Экземпляр form позволяет получать значения полей, устанавливать их и подписываться на изменения через методы:

  • form.getFieldValue(fieldName) — получение текущего значения поля.
  • form.setFieldsValue({ fieldName: value }) — установка значения поля.
  • form.validateFields() — проверка валидности всех или указанных полей.
  • form.watch — (новый в AntD 5) позволяет подписаться на изменения значений.

Связывание полей через dependencies

В Ant Design 4 и выше компонент Form.Item поддерживает свойство dependencies, которое позволяет указать, от каких полей зависит текущий:

<Form.Item
  label="Подкатегория"
  name="subcategory"
  dependencies={['category']}
  rules={[{ required: true, message: 'Выберите подкатегорию' }]}
>
  {({ getFieldValue }) => {
    const category = getFieldValue('category');
    const options = category === 'fruits'
      ? ['Яблоко', 'Банан']
      : category === 'vegetables'
      ? ['Морковь', 'Брокколи']
      : [];
    return <Select options={options.map(opt => ({ label: opt, value: opt }))} />;
  }}
</Form.Item>

Ключевые моменты:

  • dependencies — массив имен полей, изменения которых вызывают перерендер текущего Form.Item.
  • Функция в children Form.Item получает объект с методом getFieldValue, что позволяет динамически вычислять доступные значения.
  • Такой подход обеспечивает реактивность: при изменении родительского поля зависимое поле обновляется автоматически.

Пример динамического отображения полей

Иногда необходимо не только менять содержимое поля, но и его видимость:

<Form.Item label="Использовать дополнительные опции" name="enableOptions" valuePropName="checked">
  <Switch />
</Form.Item>

<Form.Item noStyle shouldUpdate={(prevValues, currentValues) => prevValues.enableOptions !== currentValues.enableOptions}>
  {({ getFieldValue }) => getFieldValue('enableOptions') && (
    <Form.Item label="Дополнительные настройки" name="extraSettings">
      <Input placeholder="Введите настройки" />
    </Form.Item>
  )}
</Form.Item>

Особенности:

  • shouldUpdate позволяет вручную контролировать, когда Form.Item должен перерендериться.
  • noStyle убирает визуальное оформление контейнера, чтобы не нарушать верстку.
  • Использование функции в children обеспечивает полный контроль над логикой отображения и значениями зависимых полей.

Валидация зависимых полей

Для зависимых полей критично правильно настроить валидацию. Ant Design предоставляет возможность использовать функцию validator для динамических правил:

<Form.Item
  label="Пароль"
  name="password"
  rules={[{ required: true, message: 'Введите пароль' }]}
>
  <Input.Password />
</Form.Item>

<Form.Item
  label="Подтверждение пароля"
  name="confirm"
  dependencies={['password']}
  rules={[
    { required: true, message: 'Подтвердите пароль' },
    ({ getFieldValue }) => ({
      validator(_, value) {
        if (!value || getFieldValue('password') === value) {
          return Promise.resolve();
        }
        return Promise.reject(new Error('Пароли не совпадают'));
      },
    }),
  ]}
>
  <Input.Password />
</Form.Item>

Выводы по валидации:

  • dependencies гарантирует, что при изменении основного поля зависимое поле также проверяется заново.
  • Использование validator позволяет реализовать условные правила, которые зависят от других полей.

Практические советы

  1. Минимизировать вычисления внутри Form.Item: лучше готовить данные заранее, если зависимость сложная.
  2. Использовать shouldUpdate для сложной логики видимости вместо dependencies, если условие зависит сразу от нескольких полей.
  3. Обновление значений зависимых полей: иногда полезно сбрасывать зависимое поле при изменении родительского через form.setFieldsValue({ fieldName: undefined }).
  4. Типизация: при использовании TypeScript рекомендуется задавать тип формы и значения, чтобы избежать ошибок при доступе к getFieldValue.

Итоговая структура зависимых полей

В типичной динамической форме с зависимостями присутствуют три уровня:

  1. Родительское поле — задает основное условие или категорию.
  2. Зависимое поле — изменяет контент или доступность в зависимости от родителя.
  3. Логика отображения и валидации — реализуется через dependencies, shouldUpdate, функции в children и кастомные валидаторы.

Такой подход обеспечивает реактивность форм и позволяет создавать гибкие интерфейсы с минимальным количеством ручного кода.