You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Ant Design Tag列表封装进Form.List实现数组值管理与提交?

问题解决方法

你遇到的Form.List初始值不生效、表单无法正确收集标签排序后的值的问题,核心是两个配置错误:

  • 优先级问题:Form.List 上单独配置的initialValue优先级低于外层Form组件的initialValues属性,只要外层Form配置了初始值,Form.List自身的initialValue就会被覆盖
  • 绑定逻辑问题:你没有正确接收Form.Item透传的表单值,自定义标签组件的增删改操作也没有和Form.List提供的方法联动,导致表单无法同步状态

正确实现逻辑

  1. 标签数组的初始值统一配置在外层Form的initialValues中,字段名和Form.List的name属性保持一致
  2. Form.List下的每个Form.Item直接透传field属性即可,不需要额外配置name,表单会自动按数组顺序维护每个标签的值
  3. 标签的删除、排序、新增操作,直接调用Form.List渲染参数提供的remove/move/add方法,不需要自己维护本地state,操作后表单值会自动更新
  4. 异步从接口获取标签列表时,拿到数据后调用form.setFieldsValue({ 对应字段名: 返回的数组 })即可自动渲染对应数量的标签
  5. 表单提交时,直接从onFinish回调或者form.getFieldValue方法拿到的就是增删、排序后的最新数组,可以直接传给接口

完整代码示例

import { Form, Tag, Button } from 'antd';
import { DragOutlined, CloseOutlined } from '@ant-design/icons';
import React, { useRef, useState } from 'react';

// 可拖拽、可关闭的自定义标签组件
const DraggableTag = ({ value, onClose, onDragStart, onDragOver, onDrop, isDragging }) => {
  return (
    <Tag
      closable
      closeIcon={<CloseOutlined />}
      onClose={(e) => {
        e.preventDefault();
        onClose();
      }}
      style={{ 
        opacity: isDragging ? 0.4 : 1, 
        padding: '4px 8px', 
        margin: '4px', 
        cursor: 'move' 
      }}
      draggable
      onDragStart={onDragStart}
      onDragOver={onDragOver}
      onDrop={onDrop}
    >
      <DragOutlined style={{ marginRight: 4 }} />
      {value}
    </Tag>
  );
};

const TagListForm = () => {
  const [form] = Form.useForm();
  const dragIndexRef = useRef(null);
  const [draggingIndex, setDraggingIndex] = useState(null);

  const handleSubmit = (values) => {
    // values.tagList 就是排序、增删后的最新数组,直接传接口即可
    console.log('提交的标签数据:', values.tagList);
  };

  return (
    <Form
      form={form}
      // 初始值统一在此配置,对应Form.List的name
      initialValues={{
        tagList: ['Tag1', 'Tag2', 'Tag3']
      }}
      onFinish={handleSubmit}
    >
      <Form.List name="tagList">
        {(fields, { remove, move, add }) => (
          <div>
            <div 
              style={{ 
                display: 'flex', 
                flexWrap: 'wrap', 
                padding: 8, 
                border: '1px solid #d9d9d9', 
                borderRadius: 6, 
                minHeight: 42 
              }}
            >
              {fields.map((field, index) => (
                <Form.Item {...field} key={field.key} noStyle>
                  {({ value }) => (
                    <DraggableTag
                      value={value}
                      isDragging={draggingIndex === index}
                      onClose={() => remove(index)}
                      onDragStart={() => {
                        dragIndexRef.current = index;
                        setDraggingIndex(index);
                      }}
                      onDragOver={(e) => e.preventDefault()}
                      onDrop={() => {
                        const fromIndex = dragIndexRef.current;
                        if (fromIndex !== index) {
                          // 调用move方法交换位置,表单值自动同步
                          move(fromIndex, index);
                        }
                        setDraggingIndex(null);
                        dragIndexRef.current = null;
                      }}
                    />
                  )}
                </Form.Item>
              ))}
            </div>
            <Button 
              style={{ marginTop: 8 }} 
              type="dashed" 
              block
              onClick={() => add(`新标签${Date.now()}`)}
            >
              + 添加标签
            </Button>
          </div>
        )}
      </Form.List>

      <Button type="primary" htmlType="submit" style={{ marginTop: 16 }}>
        提交
      </Button>
    </Form>
  );
};

export default TagListForm;

避坑提示

  • 不要额外维护本地的items状态存标签列表,所有增删改操作都走Form.List提供的方法,让表单成为唯一数据源,避免状态不同步
  • 如果用第三方拖拽库(比如react-dnd、dnd-kit),只需要在拖拽结束的回调里拿到起始和结束索引,调用move(fromIndex, toIndex)即可,不需要自己手动修改数组
  • 不要给Form.List下的Form.Item手动加name属性,透传field属性时已经自动绑定了对应数组项的字段路径,手动加name会导致值绑定错误

内容的提问来源于stack exchange,提问作者koengsen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 13:30:54