Form 表单组件

antv 的 form 组件进行封装,扩展一些常用的功能

如果文档内没有,可以尝试在在线示例内寻找

Usage

useForm 方式

下面是一个使用简单表单的示例,只有一个输入框

<template>
  <div class="m-4">
    <BasicForm
      :labelWidth="100"
      :schemas="schemas"
      :actionColOptions="{ span: 24 }"
      @submit="handleSubmit"
    />
  </div>
</template>
<script lang="ts">
  import { defineComponent } from 'vue';
  import { BasicForm, FormSchema } from '/@/components/Form';
  import { CollapseContainer } from '/@/components/Container';
  import { useMessage } from '/@/hooks/web/useMessage';
  const schemas: FormSchema[] = [
    {
      field: 'field',
      component: 'Input',
      label: '字段1',
      colProps: {
        span: 8,
      },
      defaultValue: '1',
      componentProps: {
        placeholder: '自定义placeholder',
        onChange: (e) => {
          console.log(e);
        },
      },
    },
  ];

  export default defineComponent({
    components: { BasicForm, CollapseContainer },
    setup() {
      const { createMessage } = useMessage();
      return {
        schemas,
        handleSubmit: (values: any) => {
          createMessage.success('click search,values:' + JSON.stringify(values));
        },
      };
    },
  });
</script>

template 方式

所有可调用函数见下方 Methods 说明

<template>
  <div class="m-4">
    <BasicForm
      :schemas="schemas"
      ref="formElRef"
      :labelWidth="100"
      @submit="handleSubmit"
      :actionColOptions="{ span: 24 }"
    />
  </div>
</template>
<script lang="ts">
  import { defineComponent, ref } from 'vue';
  import { BasicForm, FormSchema, FormActionType, FormProps } from '/@/components/Form';
  import { CollapseContainer } from '/@/components/Container';
  const schemas: FormSchema[] = [];

  export default defineComponent({
    components: { BasicForm, CollapseContainer },
    setup() {
      const formElRef = ref<Nullable<FormActionType>>(null);
      return {
        formElRef,
        schemas,
        setProps(props: FormProps) {
          const formEl = formElRef.value;
          if (!formEl) return;
          formEl.setProps(props);
        },
      };
    },
  });
</script>

useForm

form 组件还提供了 useForm,方便调用函数内部方法

示例

<template>
  <BasicForm @register="register" @submit="handleSubmit" />
</template>
<script lang="ts">
  import { defineComponent } from 'vue';
  import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
  import { CollapseContainer } from '/@/components/Container/index';
  import { useMessage } from '/@/hooks/web/useMessage';
  const schemas: FormSchema[] = [
    {
      field: 'field1',
      component: 'Input',
      label: '字段1',
      colProps: {
        span: 8,
      },
      componentProps: {
        placeholder: '自定义placeholder',
        onChange: (e: any) => {
          console.log(e);
        },
      },
    },
  ];

  export default defineComponent({
    components: { BasicForm, CollapseContainer },
    setup() {
      const { createMessage } = useMessage();
      const [register, { setProps }] = useForm({
        labelWidth: 120,
        schemas,
        actionColOptions: {
          span: 24,
        },
      });
      return {
        register,
        schemas,
        handleSubmit: (values: any) => {
          createMessage.success('click search,values:' + JSON.stringify(values));
        },
        setProps,
      };
    },
  });
</script>

参数介绍

const [register, methods] = useForm(props);

参数 props 内的值可以是 computed 或者 ref 类型

register

register 用于注册 useForm,如果需要使用 useForm 提供的 api,必须将 register 传入组件的 onRegister

<template>
  <BasicForm @register="register" @submit="handleSubmit" />
</template>
<script>
  export default defineComponent({
    components: { BasicForm },
    setup() {
      const [register] = useForm();
      return {
        register,
      };
    },
  });
</script>

Methods见下方说明

Methods

getFieldsValue

类型: () => Recordable;

说明: 获取表单值

setFieldsValue

类型: <T>(values: T) => Promise<void>

说明: 设置表单字段值

resetFields

类型: ()=> Promise<void>

说明: 重置表单值

validateFields

类型: (nameList?: NamePath[]) => Promise<any>

说明: 校验指定表单项

validate

类型: (nameList?: NamePath[]) => Promise<any>

说明: 校验整个表单

submit

类型: () => Promise<void>

说明: 提交表单

scrollToField

类型: (name: NamePath, options?: ScrollOptions) => Promise<void>

说明: 滚动到对应字段位置

clearValidate

类型: (name?: string | string[]) => Promise<void>

说明: 清空校验

setProps

TIP

设置表单的 props 可以直接在标签上传递,也可以使用 setProps,或者初始化直接写 useForm(props)

类型: (formProps: Partial<FormProps>) => Promise<void>

说明: 设置表单 Props

removeSchemaByField

类型: (field: string | string[]) => Promise<void>

说明: 根据 field 删除 Schema

appendSchemaByField

类型: ( schema: FormSchema, prefixField: string | undefined, first?: boolean | undefined ) => Promise<void>

说明: 插入到指定 filed 后面,如果没传指定 field,则插入到最后,当 first = true 时插入到第一个位置

updateSchema

类型: (data: Partial<FormSchema> | Partial<FormSchema>[]) => Promise<void>

说明: 更新表单的 schema, 只更新函数所传的参数

e.g

updateSchema({ field: 'filed', componentProps: { disabled: true } });
updateSchema([
  { field: 'filed', componentProps: { disabled: true } },
  { field: 'filed1', componentProps: { disabled: false } },
]);

Props

温馨提醒

除以下参数外,官方文档内的 props 也都支持,具体可以参考 antv form

属性类型默认值可选值说明版本
schemasSchema[]--表单配置,见下方 FormSchema 配置
submitOnResetbooleanfalse-重置时是否提交表单
labelColPartial<ColEx>--整个表单通用 LabelCol 配置
wrapperColPartial<ColEx>--整个表单通用 wrapperCol 配置
baseColPropsPartial<ColEx>--配置所有选子项的 ColProps,不需要逐个配置,子项也可单独配置优先与全局
baseRowStyleobject--配置所有 Row 的 style 样式
labelWidthnumber , string--扩展 form 组件,增加 label 宽度,表单内所有组件适用,可以单独在某个项覆盖或者禁用
labelAlignstring-left,rightlabel 布局
mergeDynamicDataobject--额外传递到子组件的参数 values
autoFocusFirstItembooleanfalse-是否聚焦第一个输入框,只在第一个表单项为 input 的时候作用
compactbooleanfalsetrue/false紧凑类型表单,减少 margin-bottom
sizestringdefault'default' , 'small' , 'large'向表单内所有组件传递 size 参数,自定义组件需自行实现 size 接收
disabledbooleanfalsetrue/false向表单内所有组件传递 disabled 属性,自定义组件需自行实现 disabled 接收
autoSetPlaceHolderbooleantrue true/false自动设置表单内组件的 placeholder,自定义组件需自行实现
autoSubmitOnEnterbooleanfalse true/false在 input 中输入时按回车自动提交2.4.0
rulesMessageJoinLabelbooleanfalsetrue/false如果表单项有校验,会自动生成校验信息,该参数控制是否将字段中文名字拼接到自动生成的信息后方
showAdvancedButtonbooleanfalsetrue/false是否显示收起展开按钮
emptySpannumber , Partial<ColEx>0-空白行格,可以是数值或者 col 对象 数
autoAdvancedLinenumber3-如果 showAdvancedButton 为 true,超过指定行数行默认折叠
alwaysShowLinesnumber1-折叠时始终保持显示的行数2.7.1
showActionButtonGroupbooleantruetrue/false是否显示操作按钮(重置/提交)
actionColOptionsPartial<ColEx>--操作按钮外层 Col 组件配置,如果开启 showAdvancedButton,则不用设置,具体见下方 actionColOptions
showResetButtonbooleantrue-是否显示重置按钮
resetButtonOptionsobject-重置按钮配置见下方 ActionButtonOption
showSubmitButtonbooleantrue-是否显示提交按钮
submitButtonOptionsobject-确认按钮配置见下方 ActionButtonOption
resetFunc () => Promise<void>-重置表单行为前执行自定义重置按钮逻辑() => Promise<void>;
submitFunc () => Promise<void>-自定义提交按钮逻辑() => Promise<void>;
fieldMapToTime[string, [string, string], string?][]'timestamp' ,'timestampStartDay' ,momentjs 时间格式用于将表单内时间区域的应设成 2 个字段,见下方说明

ColEx

src/components/Form/src/types/index.ts

ActionButtonOption

BasicButtonProps

export const buttonProps = {
  color: {
    type: String as PropType<ButtonColorType>,
    validator: (v) => validColors.includes(v),
    default: '',
  },
  loading: { type: Boolean },
  disabled: { type: Boolean },
  /**
   * Text before icon.
   */
  preIcon: { type: String },
  /**
   * Text after icon.
   */
  postIcon: { type: String },
  /**
   * preIcon and postIcon icon size.
   * @default: 14
   */
  iconSize: { type: Number, default: 14 },
  onClick: { type: [Function, Array] as PropType<(() => any) | (() => any)[]>, default: null },

  /**
   * 如果需要修改默认内置的重置、提交按钮的文本,可以传递这个属性,可选属性
   */
  text: { type: String },
};

fieldMapToTime

将表单内时间区域的值映射成 2 个字段

如果表单内有时间区间组件,获取到的值是一个数组,但是往往我们传递到后台需要是 2 个字段

useForm({
  fieldMapToTime: [
    // data为时间组件在表单内的字段,startTime,endTime为转化后的开始时间与结束时间
    // 'YYYY-MM-DD'为时间格式,参考moment
    ['datetime', ['startTime', 'endTime'], 'YYYY-MM-DD'],
    // 支持多个字段
    ['datetime1', ['startTime1', 'endTime1'], 'YYYY-MM-DD HH:mm:ss'],
  ],
});

// fieldMapToTime没写的时候表单获取到的值
{
  datetime: [Date(),Date()]
}
//  ['datetime', ['startTime', 'endTime'], 'YYYY-MM-DD'],等同于 dayjs(Date()).format('YYYY-MM-DD'). 之后
{
    startTime: '2020-08-12',
    endTime: '2020-08-15',
}

// ['datetime', ['startTime', 'endTime'], 'timestamp'],等同于 dayjs(Date()).unix(). 之后
{
    startTime: 1597190400,
    endTime: 1597449600,
}

// ['datetime', ['startTime', 'endTime'], 'timestampStartDay'],等同于 dayjs(Date()).startOf('day').unix(). 之后
{
    startTime: 1597190400,
    endTime: 1597449600,
}

FormSchema

属性类型默认值可选值说明
fieldstring--字段名
labelstring--标签名
subLabelstring--二级标签名灰色
suffixstring , number , ((values: RenderCallbackParams) => string / number);--组件后面的内容
changeEventstring--表单更新事件名称
helpMessagestring , string[]--标签名右侧温馨提示
helpComponentPropsHelpComponentProps--标签名右侧温馨提示组件 props,见下方 HelpComponentProps
labelWidthstring , number--覆盖统一设置的 labelWidth
disabledLabelWidthbooleanfalsetrue/false禁用 form 全局设置的 labelWidth,自己手动设置 labelCol 和 wrapperCol
componentstring--组件类型,见下方 ComponentType
componentPropsany,()=>{}--所渲染的组件的 props
rulesValidationRule[]--校验规则,见下方 ValidationRule
requiredboolean--简化 rules 配置,为 true 则转化成 [{required:true}]。2.4.0之前的版本只支持 string 类型的值
rulesMessageJoinLabelbooleanfalse-校验信息是否加入 label
itemPropsany--参考下方 FormItem
colPropsColEx--参考上方 actionColOptions
defaultValueobject--所渲渲染组件的初始值
render(renderCallbackParams: RenderCallbackParams) => VNode / VNode[] / string--自定义渲染组件
renderColContent(renderCallbackParams: RenderCallbackParams) => VNode / VNode[] / string--自定义渲染组件(需要自行包含 formItem)
renderComponentContent(renderCallbackParams: RenderCallbackParams) => any / string--自定义渲染组内部的 slot
slotstring--自定义 slot,渲染组件
colSlotstring--自定义 slot,渲染组件 (需要自行包含 formItem)
show boolean / ((renderCallbackParams: RenderCallbackParams) => boolean)--动态判断当前组件是否显示,css 控制,不会删除 dom
ifShow boolean / ((renderCallbackParams: RenderCallbackParams) => boolean)--动态判断当前组件是否显示,js 控制,会删除 dom
dynamicDisabledboolean / ((renderCallbackParams: RenderCallbackParams) => boolean) --动态判断当前组件是否禁用
dynamicRulesboolean / ((renderCallbackParams: RenderCallbackParams) => boolean)--动态判返当前组件你校验规则

RenderCallbackParams

export interface RenderCallbackParams {
  schema: FormSchema;
  values: any;
  model: any;
  field: string;
}

componentProps

  • 当值为对象类型时,该对象将作为component所对应组件的的 props 传入组件

  • 当值为一个函数时候

参数有 4 个

schema: 表单的整个 schemas

formActionType: 操作表单的函数。与 useForm 返回的操作函数一致

formModel: 表单的双向绑定对象,这个值是响应式的。所以可以方便处理很多操作

tableAction: 操作表格的函数,与 useTable 返回的操作函数一致。注意该参数只在表格内开启搜索表单的时候有值,其余情况为null,

{
  // 简单例子,值改变的时候操作表格或者修改表单内其他元素的值
  component:'Input',
  componentProps: ({ schema, tableAction, formActionType, formModel }) => {
    return {
      // xxxx props
      onChange:e=>{
        const {reload}=tableAction
        reload()
        // or
        formModel.xxx='123'
      }
    };
  };
}

HelpComponentProps

export interface HelpComponentProps {
  maxWidth: string;
  // 是否显示序号
  showIndex: boolean;
  // 文本列表
  text: any;
  // 颜色
  color: string;
  // 字体大小
  fontSize: string;
  icon: string;
  absolute: boolean;
  // 定位
  position: any;
}

ComponentType

schema 内组件的可选类型

export type ComponentType =
  | 'Input'
  | 'InputGroup'
  | 'InputPassword'
  | 'InputSearch'
  | 'InputTextArea'
  | 'InputNumber'
  | 'InputCountDown'
  | 'Select'
  | 'ApiSelect'
  | 'TreeSelect'
  | 'RadioButtonGroup'
  | 'RadioGroup'
  | 'Checkbox'
  | 'CheckboxGroup'
  | 'AutoComplete'
  | 'Cascader'
  | 'DatePicker'
  | 'MonthPicker'
  | 'RangePicker'
  | 'WeekPicker'
  | 'TimePicker'
  | 'Switch'
  | 'StrengthMeter'
  | 'Upload'
  | 'IconPicker'
  | 'Render'
  | 'Slider'
  | 'Rate'
  | 'Divider'; // v2.7.2新增

Divider schema 说明

Divider类型用于在schemas中占位,将会渲染成一个分割线(始终占一整行的版面),可以用于较长表单的版面分隔。请只将 Divider 类型的 schema 当作一个分割线,而不是一个常规的表单字段。

  • Divider仅在showAdvancedButton为 false 时才会显示(也就是说如果启用了表单收起和展开功能,Divider将不会显示)
  • Divider 使用schema中的label以及helpMessage来渲染分割线中的提示内容
  • Divider 可以使用componentProps来设置除type之外的 props
  • Divider 不会渲染AFormItem,因此schema中除labelcomponentPropshelpMessagehelpComponentProps以外的属性不会被用到

自行添加需要的组件类型

src/components/Form/src/componentMap.ts 内,添加需要的组件,并在上方 ComponentType 添加相应的类型 key

方式 1

这种写法适用与适用频率较高的组件

componentMap.set('componentName', 组件);

// ComponentType
export type ComponentType = xxxx | 'componentName';

方式 2

使用 useComponentRegister 进行注册

这种写法只能在当前页使用,页面销毁之后会从 componentMap 删除相应的组件

import { useComponentRegister } from '@/components/form/index';

import { StrengthMeter } from '@/components/strength-meter/index';

useComponentRegister('StrengthMeter', StrengthMeter);

提示

方式 2 出现的原因是为了减少打包体积,如果某个组件体积很大,用方式 1 的话可能会使首屏体积增加

render

自定义渲染内容

<template>
  <div class="m-4">
    <BasicForm @register="register" @submit="handleSubmit" />
  </div>
</template>
<script lang="ts">
  import { defineComponent, h } from 'vue';
  import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { Input } from 'ant-design-vue';
  const schemas: FormSchema[] = [
    {
      field: 'field1',
      component: 'Input',
      label: '字段1',
      colProps: {
        span: 8,
      },
      rules: [{ required: true }],
      render: ({ model, field }) => {
        return h(Input, {
          placeholder: '请输入',
          value: model[field],
          onChange: (e: ChangeEvent) => {
            model[field] = e.target.value;
          },
        });
      },
    },
    {
      field: 'field2',
      component: 'Input',
      label: '字段2',
      colProps: {
        span: 8,
      },
      rules: [{ required: true }],
      renderComponentContent: () => {
        return {
          suffix: () => 'suffix',
        };
      },
    },
  ];
  export default defineComponent({
    components: { BasicForm },
    setup() {
      const { createMessage } = useMessage();
      const [register, { setProps }] = useForm({
        labelWidth: 120,
        schemas,
        actionColOptions: {
          span: 24,
        },
      });
      return {
        register,
        schemas,
        handleSubmit: (values: any) => {
          createMessage.success('click search,values:' + JSON.stringify(values));
        },
        setProps,
      };
    },
  });
</script>

slot

自定义渲染内容

提示

使用插槽自定义表单域时,请注意 antdv 有关 FormItem 的相关说明

<template>
  <div class="m-4">
    <BasicForm @register="register">
      <template #customSlot="{ model, field }">
        <a-input v-model:value="model[field]" />
      </template>
    </BasicForm>
  </div>
</template>
<script lang="ts">
  import { defineComponent } from 'compatible-vue';
  import { BasicForm, useForm } from '@/components/Form/index';
  import { BasicModal } from '@/components/modal/index';
  export default defineComponent({
    name: 'FormDemo',
    setup(props) {
      const [register] = useForm({
        labelWidth: 100,
        actionColOptions: {
          span: 24,
        },
        schemas: [
          {
            field: 'field1',
            label: '字段1',
            slot: 'customSlot',
          },
        ],
      });
      return {
        register,
      };
    },
  });
</script>

ifShow/show/dynamicDisabled

自定义显示/禁用

<template>
  <div class="m-4">
    <BasicForm @register="register" />
  </div>
</template>
<script lang="ts">
  import { defineComponent } from 'vue';
  import { BasicForm, FormSchema, useForm } from '/@/components/Form/index';
  const schemas: FormSchema[] = [
    {
      field: 'field1',
      component: 'Input',
      label: '字段1',
      colProps: {
        span: 8,
      },
      show: ({ values }) => {
        return !!values.field5;
      },
    },
    {
      field: 'field2',
      component: 'Input',
      label: '字段2',
      colProps: {
        span: 8,
      },
      ifShow: ({ values }) => {
        return !!values.field6;
      },
    },
    {
      field: 'field3',
      component: 'DatePicker',
      label: '字段3',
      colProps: {
        span: 8,
      },
      dynamicDisabled: ({ values }) => {
        return !!values.field7;
      },
    },
  ];

  export default defineComponent({
    components: { BasicForm },
    setup() {
      const [register, { setProps }] = useForm({
        labelWidth: 120,
        schemas,
        actionColOptions: {
          span: 24,
        },
      });
      return {
        register,
        schemas,
        setProps,
      };
    },
  });
</script>

antv form

Slots

名称说明
formFooter表单底部区域
formHeader表单顶部区域
resetBefore重置按钮前
submitBefore提交按钮前
advanceBefore展开按钮前
advanceAfter展开按钮后

ApiSelect

远程下拉加载组件,该组件可以用于学习参考如何自定义组件集成到 Form 组件内,将自定义组件交由 Form 去管理

Usage

const schemas: FormSchema[] = [
  {
    field: 'field',
    component: 'ApiSelect',
    label: '字段',
  },
];

Props

属性类型默认值说明
numberToStringbooleanfalse是否将number值转化为string
api()=>Promise<{ label: string; value: string; disabled?: boolean }[]>-数据接口,接受一个 Promise 对象
paramsobject-接口参数。此属性改变时会自动重新加载接口数据
resultFieldstring-接口返回的字段,如果接口返回数组,可以不填。支持x.x.x格式
labelFieldstringlabel下拉数组项内label显示文本的字段,支持x.x.x格式
valueFieldstringvalue下拉数组项内value实际值的字段,支持x.x.x格式
immediatebooleantrue是否立即请求接口,否则将在第一次点击时候触发请求

ApiTreeSelect

远程下拉树加载组件,和ApiSelect类似,2.6.1 以上版本

Props

属性类型默认值说明
api()=>Promise<{ label: string; value: string; children?: any[] }[]>-数据接口,接受一个 Promise 对象
paramsobject-接口参数。此属性改变时会自动重新加载接口数据
resultFieldstring-接口返回的字段,如果接口返回数组,可以不填。支持x.x.x格式
immediatebooleantrue是否立即请求接口。

RadioButtonGroup

Radio Button 风格的选择按钮

Usage

const schemas: FormSchema[] = [
  {
    field: 'field',
    component: 'RadioButtonGroup',
    label: '字段',
  },
];

Props

属性类型默认值说明
options{ label: string; value: string; disabled?: boolean }[]-数据字段