Antd v4: Как добавить вложенность в ‹Form.List›?

Я пытаюсь создать настраиваемую сетку, подобную структуре.
Структура будет состоять из различных строк, и каждая строка может иметь несколько столбцов. И в каждом столбце будет 1-2 поля формы.

В Antd v4.2.0 у нас есть <Form.List /> компонент, который помогает нам создавать динамические формы.

Я попытался использовать его, и это было нормально для части динамической строки, но я не могу понять, как я могу создать несколько столбцов, т.е. <Form.List> внутри <Form.List>

Я также могу создать эту сетку вручную, но я хочу также использовать проверку формы в этой сетке.

Визуальное представление того, что я пытаюсь создать:

введите здесь описание изображения


person Parth Mistry    schedule 05.05.2020    source источник
comment
есть работа?   -  person Jaison James    schedule 22.05.2020
comment
Единственное обходное решение, о котором я думаю, - это не использовать ‹Form.List /› и пытаться использовать вложенные массивы старой школы: массив столбцов внутри массива строк. @ Джейсон.   -  person Parth Mistry    schedule 22.05.2020
comment
Спасибо, я наконец-то возвращаюсь к старому школьному методу, надеюсь, они найдут решение позже ...   -  person Jaison James    schedule 23.05.2020


Ответы (1)


Чтобы добавить вложенный элемент <Form.List> в другой <Form.List>, просто добавьте вложенный список во внешний цикл списка, как любой другой вложенный <Form.Item>. Хитрость заключается в том, чтобы правильно установить вложенное свойство <Form.List> name, используя формат: <Form.List name={[field.name, 'nested-input-name']}>.

В качестве примера давайте расширим пример динамической формы из официальной документации (https://ant.design/components/form/#components-form-demo-dynamic-form-item) с вложенным списком. В исходном примере добавляются поля для имени и фамилии, поэтому мы добавим вложенный список для псевдонимов.

import { Form, Input, Button, Space } from 'antd';
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';

const Demo = () => {
  const onFinish = values => {
    console.log('Received values of form:', values);
  };

  return (
    <Form name="dynamic_form_nest_item" onFinish={onFinish} autoComplete="off">
      <Form.List name="users">
        {(fields, { add, remove }) => {
          return (
            <div>
              {fields.map(field => (
                <>
                    <Space key={field.key} style={{ display: 'flex', marginBottom: 8 }} align="start">
                      <Form.Item
                        {...field}
                        name={[field.name, 'first']}
                        fieldKey={[field.fieldKey, 'first']}
                        rules={[{ required: true, message: 'Missing first name' }]}
                      >
                        <Input placeholder="First Name" />
                      </Form.Item>
                      <Form.Item
                        {...field}
                        name={[field.name, 'last']}
                        fieldKey={[field.fieldKey, 'last']}
                        rules={[{ required: true, message: 'Missing last name' }]}
                      >
                        <Input placeholder="Last Name" />
                      </Form.Item>

                      <MinusCircleOutlined
                        onClick={() => {
                          remove(field.name);
                        }}
                      />
                    </Space>
                
                    <Form.List name={[field.name, 'nicknames']}>
                        {(nicknames, { add, remove }) => {
                          return (
                            <div>
                              {nicknames.map(nickname => (
                                <Space key={nickname.key} align="start">
                                  <Form.Item
                                    {...nickname}
                                    name={[nickname.name, 'nickname']}
                                    fieldKey={[nickname.fieldKey, 'nickname']}
                                    rules={[{ required: true, message: 'Missing nickname' }]}
                                  >
                                    <Input placeholder="Nickname" />
                                  </Form.Item>

                                  <MinusCircleOutlined
                                    onClick={() => {
                                      remove(nickname.name);
                                    }}
                                  />
                                </Space>
                              ))}

                              <Form.Item>
                                <Button
                                  type="dashed"
                                  onClick={() => {
                                    add();
                                  }}
                                  block
                                >
                                  <PlusOutlined /> Add nickname
                                </Button>
                              </Form.Item>
                            </div>
                          );
                        }}
                    </Form.list>
                </>
              ))}

              <Form.Item>
                <Button
                  type="dashed"
                  onClick={() => {
                    add();
                  }}
                  block
                >
                  <PlusOutlined /> Add field
                </Button>
              </Form.Item>
            </div>
          );
        }}
      </Form.List>

      <Form.Item>
        <Button type="primary" htmlType="submit">
          Submit
        </Button>
      </Form.Item>
    </Form>
  );
};

ReactDOM.render(<Demo />, mountNode);

Я придерживаюсь однокомпонентного стиля официальной документации, но вы, вероятно, захотите разбить его на более мелкие компоненты в реальном приложении.

person okebinda    schedule 24.09.2020