使用antd-form-render配置各类表单

基于react,antd v4 搭配antd-form-render可以轻松实现各类表单

尝试地址: github.com/leonwgc/ant…

  1. 一行一列布局

demo1.png

import React from 'react';
import styled from 'styled-components';
import { Form, Button, Space, Input, message } from 'antd';
import FormRender from 'antd-form-render';

const StyledOneRow = styled.div`
  width: 400px;
`;

const OneCol = () => {
  const [form] = Form.useForm();

  const oneRowLayout = [
    {
      type: Input,
      label: '手机号',
      placeholder: '请输入',
      name: 'tel',
      elProps: {
        maxLength: 11,
      },
      itemProps: {
        rules: [
          { required: true, message: '请输入' },
          { pattern: /^1\d{10}$/, message: '手机号必须为11位数字' },
        ],
      },
    },
    {
      type: Input.Password,
      label: '密码',
      placeholder: '请输入',
      name: 'pwd',
      itemProps: {
        rules: [{ required: true, message: '请输入' }],
      },
    },
    {
      type: Input.Password,
      label: '确认密码',
      placeholder: '请输入',
      name: 'confirmPwd',
      itemProps: {
        rules: [
          { required: true, message: '请输入' },
          ({ getFieldValue }) => ({
            validator(_, value) {
              if (!value || getFieldValue('pwd') === value) {
                return Promise.resolve();
              }
              return Promise.reject(new Error('两次密码不一致'));
            },
          }),
        ],
      },
    },
    {
      type: Input.TextArea,
      name: 'desc',
      label: '简介',
      elProps: {
        placeholder: '个人简介',
        rows: 4,
      },
    },
    {
      // 自定义render
      render() {
        return (
          <Form.Item wrapperCol={{ offset: 6 }}>
            <Space>
              <Button htmlType="submit" type="primary">
                确定
              </Button>
              <Button htmlType="reset">重置</Button>
            </Space>
          </Form.Item>
        );
      },
    },
  ];

  return (
    <StyledOneRow>
      <Form
        form={form}
        labelCol={{ span: 6 }}
        onFinish={(v) => {
          message.success(JSON.stringify(v));
        }}
      >
        <FormRender layoutData={oneRowLayout}></FormRender>
      </Form>
    </StyledOneRow>
  );
};

export default OneCol;

复制代码
  1. 一行多列布局

demo2.png

import React, { useState } from 'react';
import styled from 'styled-components';
import { Input, Radio, Form } from 'antd';
import FormRender from 'antd-form-render';

const StyledOneRow = styled.div`
  width: 800px;
`;

const MultipleCols = () => {
  const layout = [];
  const [cols, setCols] = useState(4);

  for (let i = 0; i < 11; i++) {
    layout.push({
      type: Input,
      label: `输入框${i + 1}`,
      placeholder: '请输入',
      name: `name${i}`,
    });
  }

  return (
    <StyledOneRow>
      <Form layout="vertical">
        <div style={{ margin: '16px 0' }}>
          <Radio.Group
            onChange={(e) => setCols(Number(e.target.value))}
            optionType="button"
            value={cols}
          >
            <Radio value={1}>1行1列</Radio>
            <Radio value={2}>1行2列</Radio>
            <Radio value={3}>1行3列</Radio>
            <Radio value={4}>1行4列</Radio>
          </Radio.Group>
        </div>
        <FormRender layoutData={layout} cols={cols}></FormRender>
      </Form>
      <FormRender layoutData={layout}></FormRender>
    </StyledOneRow>
  );
};

export default MultipleCols;

复制代码
  1. 等间距排列 (常用于列表页面的搜索等)

demo3.png

import React, { useState } from 'react';
import styled from 'styled-components';
import { Input, Radio, Form } from 'antd';
import { FormSpaceRender } from 'antd-form-render';

const StyledOneRow = styled.div`
  width: 1000px;
`;

const SpaceLayout = () => {
  const layout = [];
  const [space, setSpace] = useState(8);

  for (let i = 0; i < 3; i++) {
    layout.push({
      type: Input,
      label: `输入框${i + 1}`,
      placeholder: '请输入',
      name: `name${i}`,
    });
  }

  return (
    <StyledOneRow>
      <Form layout="horizontal">
        <div style={{ margin: '16px 0' }}>
          <Radio.Group
            onChange={(e) => setSpace(Number(e.target.value))}
            optionType="button"
            value={space}
          >
            <Radio value={8}>8px</Radio>
            <Radio value={16}>16px</Radio>
            <Radio value={24}>24px</Radio>
            <Radio value={32}>32px</Radio>
          </Radio.Group>
        </div>
        <FormSpaceRender layoutData={layout} size={space}></FormSpaceRender>
      </Form>
    </StyledOneRow>
  );
};

export default SpaceLayout;

复制代码

4.表单联动

demo4.png

import React, { useState } from 'react';
import styled from 'styled-components';
import { Form, Button, Radio, message } from 'antd';
import FormRender from 'antd-form-render';

const StyledOneRow = styled.div`
  width: 600px;
`;

const StyledP = styled.p`
  padding: 10px;
`;

const OneColWithDynamicControl = () => {
  const [form] = Form.useForm();

  const [form1] = Form.useForm();

  // 用于同步表单状态
  const [data, setData] = useState({});

  const layout = [
    {
      type: Radio.Group,
      label: '性别',
      name: 'gender',
      elProps: {
        options: [
          { label: '男', value: '男生' },
          { label: '女', value: '女生' },
        ],
      },
    },
    {
      type: 'div',
      label: '你是',
      elProps: {
        children: data.gender || '未选择',
      },
    },
    {
      type: Button,
      elProps: {
        htmlType: 'submit',
        type: 'primary',
        children: '确定',
      },
      itemProps: {
        wrapperCol: { offset: 6 },
      },
    },
  ];

  // 基于antd , dependency 实现表单联动
  const layout1 = [
    {
      type: Radio.Group,
      label: '性别',
      name: 'gender',
      elProps: {
        options: [
          { label: '男', value: '男生' },
          { label: '女', value: '女生' },
        ],
      },
    },
    {
      render() {
        return (
          <Form.Item label="你是" dependencies={['gender']}>
            {() => {
              const gender = form1.getFieldValue('gender');
              return gender || '未选择';
            }}
          </Form.Item>
        );
      },
    },
    {
      type: Button,
      elProps: {
        htmlType: 'submit',
        type: 'primary',
        children: '确定',
      },
      itemProps: {
        wrapperCol: { offset: 6 },
      },
    },
  ];

  return (
    <StyledOneRow>
      <StyledP>1.定义onValuesChange 同步状态到state , 触发重新渲染实现表单联动</StyledP>
      <Form
        form={form}
        onValuesChange={(v) => {
          setData((p) => ({ ...p, ...v }));
        }}
        labelCol={{ span: 6 }}
        onFinish={(v) => {
          message.success(JSON.stringify(v));
        }}
      >
        <FormRender layoutData={layout}></FormRender>
      </Form>

      <StyledP>2.利用Form.Item dependencies 和自定义render 实现表单联动</StyledP>
      <Form
        form={form1}
        labelCol={{ span: 6 }}
        onFinish={(v) => {
          message.success(JSON.stringify(v));
        }}
      >
        <FormRender layoutData={layout1}></FormRender>
      </Form>
    </StyledOneRow>
  );
};

export default OneColWithDynamicControl;

复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享