npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

antd-form-multi

v4.0.2

Published

基于antd,通过配置项生成表单,并且拥有表单内数据联动、多级列表控制等功能

Readme

antd-form-multi

背景

在前端中后台的开发中,常见的业务场景是对表单的处理。对于简单、交互少、联动少的业务场景直接使用antd提供的Form组件就可以,对于追求性能,需要复杂表单生成的时候可以使用 formily 开源库,但其付出的学习成本会更高。所以本库是介于两者之间的一个便捷、高效、易于理解、且功能相对完整、适用于绝大多数业务场景开发的一个库。

特性

  • 高效:自定义的配置项生成表单。
  • 强大:拥有表单内数据联动,多级列表控制等功能
  • 简单:其中基于 AntdV4 ,所有组件 API 保持一致,降低开发人员心智负担。

安装

npm install antd-form-multi

或者

yarn add antd-form-multi

在组件内的<Form>(antd组件)内引用

import FormItem from 'antd-form-multi'

用法和实例说明

基础用法

import React from 'react';
import { connect } from 'dva';
import { Form } from 'antd';
import FormItem from 'antd-form-multi';

const Index = (props) => {
  const [form] = Form.useForm();
  return (
    <>
      <Form form={form} layout="vertical" initialValues={{}}>
        <FormItem
          ref={form}
          fields={[
            {
              type: 'text',
              required: true,
              label: '标题',
              code: 'title',
              span: 24,
            },
            {
              type: 'textarea',
              label: '备注',
              code: 'remark',
              span: 10,
            },
          ]}
          labelCol={24}
          wrapperCol={24}
        ></FormItem>
      </Form>
    </>
  );
}
  • ref 为表单实例项
  • fields 表单内每一控件的配置信息,详情配置信息参考下文(fields配置项)
  • labelCol、wrapperCol 每一项的标签和输入控件的布局样式

数据联动

        const [groupValue, setGroupValue] = useState([]);
        ...
        <FormItem
          ref={form}
          fields={[
            {
              type: 'select',
              required: true,
              label: '规则选择(一)',
              code: 'rules1',
              span: 24,
              options: [
                {
                  id: '1-1',
                  name: '规则1-1',
                },
                {
                  id: '1-2',
                  name: '规则1-2',
                },
              ],
              onChange: (val) => {
                const index = groupValue.findIndex((i) => i === '1-1' || i === '1-2');
                if (index > -1) {
                  groupValue.splice(index, 1, val);
                } else {
                  groupValue.push(val);
                }
                setGroupValue([...groupValue]);
              },
            },
            {
              type: 'select',
              required: true,
              label: '规则选择(二)',
              code: 'rules2',
              span: 24,
              options: [
                {
                  id: '2-1',
                  name: '规则2-1',
                },
                {
                  id: '2-2',
                  name: '规则2-2',
                },
              ],
              onChange: (val) => {
                const index = groupValue.findIndex((i) => i === '2-1' || i === '2-2');
                if (index > -1) {
                  groupValue.splice(index, 1, val);
                } else {
                  groupValue.push(val);
                }
                setGroupValue([...groupValue]);
              },
            },
            {
              type: 'text',
              label: '我是规则1-1',
              code: 'rule1-1',
              span: 24,
              group: ['1-1'],
            },
            {
              type: 'text',
              label: '我是规则1-2或2-1',
              code: 'rule1-2,2-1',
              span: 24,
              group: ['1-2', '2-1'],
            },
            {
              type: 'text',
              required: true,
              label: '规则2-2 必填',
              code: 'rule2-2',
              span: 24,
              group: ['2-2'],
            },
            {
              type: 'text',
              label: '规则不是2-2 非必填',
              code: 'rule2-2',
              span: 24,
              group: ['1-1', '1-2', '2-1'],
            },
          ]}
          groupValue={groupValue}
          labelCol={24}
          wrapperCol={24}
        ></FormItem>

采用组的概念,将需要显示的内容全部传入fields内,当groupValue 内匹配有 group 时则该项显示,如果field没有group 则一值展示

所以你只需要在触发改变group 时进行配置即可

一级列表

二级列表

    import FormItem, { FormWrapCard, addLevel1 } from '@/components/FormItem';
    ...
      const addHandle = () => {
        addLevel1(form, ['list'], {});
      };
      <Form form={form} layout="vertical" initialValues={{}}>
        <FormItem
          ref={form}
          fields={[
            {
              type: 'text',
              required: true,
              label: '标题',
              code: 'title',
              span: 24,
            },
          ]}
          level1={{
            name: ['list'],
            fields: [
              {
                type: 'text',
                label: '键',
                code: 'key',
                span: 12,
              },
              {
                type: 'text',
                label: '值',
                code: 'value',
                span: 12,
              },
            ],
            WrapComponent: FormWrapCard,
            wrapCopy: true,
            wrapMove: true,
            openLabel: true,
          }}
          labelCol={24}
          wrapperCol={24}
        ></FormItem>
      </Form>
      <Button onClick={addHandle}> 添加一项</Button>

level1

level1 的配置项参考下方API

这里提供了增加一级列表的函数

addLevel1:(form:表单的ref,[]:一级列表的名称,{}:一级列表的默认值)=>void

level2

二级列表的API与一级列表保持一致

一级列表-联动

基本与 数据联动一致,通过改变level1 内的groupValue的值显示/隐藏对应组的field,

这里是隐藏,当切换,使得隐藏的显示时,隐藏的输入控件的内容会被保留,但表单提交时,也会保留 如果不希望保留得话,需要手动清除值

groupValue

是一个数据集合,例如

groupValue = [[0,['group1']],[1,['group2','group3']]]

第一项 0name对应的 一级列表 的索引,第二项 ['group1']是一个数组,对应的是该索引列表的组的规则,满足规则的 field 项显示

当 fields 其中一项改变时,接收的参数为2个,第一个是改变的值,第二个是改变的 name 的索引值

例如

     {
        type: 'select',
        required: true,
        label: '规则选择(一)',
        code: 'rules1',
        span: 12,
        options: [
            {
            id: '1-1',
            name: '规则1-1',
            },
            {
            id: '1-2',
            name: '规则1-2',
            },
        ],
        onChange: (val, nameList) => {
            const index = groupListValue.findIndex((i) => i[0] === nameList[0]);
            const name = nameList[0];
            if (index > -1) {
                groupListValue.splice(index, 1, [name, [val]]);
            } else {
                groupListValue.push([name, [val]]);
            }
            setGroupListValue([...groupListValue]);
        },
    },

我们可以通过onChange回调函数来接收到这两个参数,并且通过自己的方式去改变对应组的值

二级列表-联动

基本上与一级列表一致 在组的定义上,多了一层

groupValue = [[0,0,['group1']],[0,1,['group2','group3']]]

第一项 0 是一级列表对应的索引,第二项是二级列表 name对应的索引, 第三项 ['group1']是一个数组,对应的是该索引列表的组的规则,满足规则的 field 项显示

当 fields 其中一项改变时,接收的参数为3个,第一个是改变的值,第二个是改变的 name 的索引值,第三个是上级/第一级的索引值

API

fields配置项

type

| 参数 | 说明 | | --- | --- | | datePicker | 日期选择器 | | rangePicker | 日期范围选择器 | | timePicker | 时间选择器 | | timeRangePicker | 时间范围选择器 | | switch | 开关 | | radio | 圆形单选框 | | radio_button | 方形单选框 | | checkbox | 复选框 | | text | 输入框 | | password | 密码输入框 | | text_group | 输入组 | | textarea | 输入框-文本域 | | number_text | 数字输入框 | | select | 选择框 | | select_multi | 多选框 | | autoComplete | 自动完成 | | upload | 文件上传 | | transfer | 穿梭框 | | table | 表格 | | template | 自定义 |

code

对应 antd 文档的 name

span

表示控件的占位大小(24份大小)

其余

antd 文档API 一致

配置项

| 参数 | 说明 | 类型 | 默认值| | --- | --- | --- | --- | | fields | 列表的表单配置 | Array | - | | labelCol | 表单的label占位宽度 | Number | 6 | | wrapperCol | 表单的wrapper占位宽度 | Number | 18 | | offset | 表单的offset占位宽度 | Number | null | | plugin | 自行添加的组件插件 | [] | [] |

plugin

  • 类型 Array 包含多个对象,对象内字段为
    • type(String):对应fields 内的 type,如果与 fields配置项冲突,则使用该type
    • component(Function):接收 item 字段,该字段包含传入的配置参数,field包含改项的位置参数。返回值:一个组件
  • 示例
    plygin=[
      {
          type:'input',
          component:(item,field)=><input></input>
      }
    ]

level1 配置项

| 参数 | 说明 | 类型 | 默认值| | --- | --- | --- | --- | | name | 列表的名称 | Array | - | | fields | 列表的表单配置 | Array | - | | rules | 列表的规则(参照 antd 的配置) | Array | - | | openLabel | 列表的标题显示 | Boolean | false | | labelCol | 表单的label占位宽度 | Number | 6 | | wrapperCol | 表单的wrapper占位宽度 | Number | 18 | | offset | 表单的offset占位宽度 | Number | null | | WrapComponent | 包裹组件 | React.Element | <></> | | wrapName | 包裹组件的名称 | String | '新的标签页' | | wrapCopy | 包裹组件复制操作 | Boolean | false | | wrapMove | 包裹组件移动操作 | Boolean | false | | sortable | 包裹组件可拖拽 | Boolean | false |

level2 配置项与 level1 一致

level2配置暂不支持

| sortable | 包裹组件可拖拽 | Boolean | false | | --- | --- | --- | ---|