antd-form-render

Develop antD forms using JS configuration

The installation

Install using NPM NPM/YARN:

$ npm install --save antd-form-render
$ yarn add antd-form-render
Copy the code

function

  1. Develop antD V4 forms through A JS configuration
  2. 1 Row, 1 column, 1 Row, 2 columns, 1 Row, 3 columns, 1 Row, 4 columns (based on Row and Col)
  3. Equally spaced layout (Space based arrangement)

1. Row by column

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: 'Mobile phone Number'.placeholder: 'Please enter'.name: 'tel'.elProps: {
        maxLength: 11,},itemProps: {
        rules: [{required: true.message: 'Please enter' },
          { pattern: /^1\d{10}$/, message: 'Mobile phone number must be 11 digits'},],},}, {type: Input.Password,
      label: 'password'.placeholder: 'Please enter'.name: 'pwd'.itemProps: {
        rules: [{ required: true.message: 'Please enter'}],}}, {type: Input.Password,
      label: 'Confirm password'.placeholder: 'Please enter'.name: 'confirmPwd'.itemProps: {
        rules: [{required: true.message: 'Please enter' },
          ({ getFieldValue }) = > ({
            validator(_, value) {
              if(! value || getFieldValue('pwd') === value) {
                return Promise.resolve();
              }
              return Promise.reject(new Error('Two different passwords')); },},],},}, {type: Input.TextArea,
      name: 'desc'.label: 'introduction'.elProps: {
        placeholder: 'Personal Profile'.rows: 4,}}, {// Customize render
      render() {
        return (
          <Form.Item wrapperCol={{ offset: 6}} >
            <Space>
              <Button htmlType="submit" type="primary">determine</Button>
              <Button htmlType="reset">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;

Copy the code

2. Layout with one row and multiple columns

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: ` input box${i + 1}`.placeholder: 'Please enter'.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}>Row 1 column 1</Radio>
            <Radio value={2}>1 row 2 column</Radio>
            <Radio value={3}>1 line 3 columns</Radio>
            <Radio value={4}>1 line 4 columns</Radio>
          </Radio.Group>
        </div>
        <FormRender layoutData={layout} cols={cols}></FormRender>
      </Form>
    </StyledOneRow>
  );
};

export default MultipleCols;

Copy the code

3. Equally spaced arrangement (often used to search list pages, etc.)

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: ` input box${i + 1}`.placeholder: 'Please enter'.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;

Copy the code

4. Form linkage

  1. Define the form onValuesChange to synchronize the state to the external state and trigger rerendering to implement form linkage (full rendering)
  2. . Use the Form Item dependencies/shouldUpdate and custom render implement Form linkage (not a full volume rendering)

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();

  // Used to synchronize form state
  const [data, setData] = useState({});

  const layout = [
    {
      type: Radio.Group,
      label: 'gender'.name: 'gender'.elProps: {
        options: [{label: 'male'.value: 'the boys' },
          { label: 'woman'.value: 'the girl'},],},}, {type: 'div'.label: 'are you'.elProps: {
        children: data.gender || 'Not selected'}, {},type: Button,
      elProps: {
        htmlType: 'submit'.type: 'primary'.children: 'sure',},itemProps: {
        wrapperCol: { offset: 6}},},];// Form linkage based on ANTd Dependency
  const layout1 = [
    {
      type: Radio.Group,
      label: 'gender'.name: 'gender'.elProps: {
        options: [{label: 'male'.value: 'the boys' },
          { label: 'woman'.value: 'the girl'},],},}, {render() {
        return (
          <Form.Item label="Are you" dependencies={['gender']} >{() => { const gender = form1.getFieldValue('gender'); Return gender | | 'no choice'; }}</Form.Item>); }, {},type: Button,
      elProps: {
        htmlType: 'submit'.type: 'primary'.children: 'sure',},itemProps: {
        wrapperCol: { offset: 6}},},];return (
    <StyledOneRow>
      <StyledP>1. Define onValuesChange to synchronize the status to state to trigger re-rendering for form linkage</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. Use the Form. The Item dependencies/shouldUpdate and custom render Form linkage</StyledP>
      <Form
        form={form1}
        labelCol={{ span: 6 }}
        onFinish={(v)= > {
          message.success(JSON.stringify(v));
        }}
      >
        <FormRender layoutData={layout1}></FormRender>
      </Form>
    </StyledOneRow>
  );
};

export default OneColWithDynamicControl;

Copy the code

Component Type Definition

export declare type FormRenderProps = {
    /** * one-dimensional array: Place a form item on the bottom line. If COLS =2/3/4, place COLS (2/3/4) in one line
    layoutData: Item[] | Item[][]; cols? :1 | 2 | 3 | 4;
};

// Equally spaced layout components
import type { SpaceProps } from 'antd';
export declare type SpaceLayoutProps = SpaceProps & {
  layoutData: Item[];
};

export declare type Item = {
    /** Component types, such as Input,Button," Input "*/type? : React.ComponentType | string;/** The name passed to the form. Item as the Form data key */name? : string;/** label name */label? : string;/** render */render? :() = > React.ReactNode;
    /** dynamically returns Item with precedence over render */getJSON? :() = > Item | null;
    /** Component props, such as Button,Input props, are passed transparently to the component defined by type */elProps? : Record<string, unknown>;/** props for form. Item is passed through to form. Item */itemProps? : Record<string, unknown>;/** rules for form. Item, as defined in itemPropsrules? : Rule[]; };Copy the code