SchemaForm - JSON 表单
通过一个配置式的 schema 来生成表单。schema 与 Antd Table 的 columns 非常类似。
基本概念
一个基本的 Schema 表单:
在开始深入之前,让我们先来了解几个重要的概念。
SchemaForm 的底层还是 Antd Form 组件。它通过遍历 schema 数组 来生成表单项。
以这个例子来说,columns 数组 中的每一个对象都是一个 schema。
{
title: '用户名',
dataIndex: 'username',
fieldProps: {
Placeholder: '请输入用户名'
},
formItemProps: {
rules: [
{
required: true,
},
],
},
},
如果用 Antd Form 的方式来书写,那么这个 schema 生成的表单项是这样的:
import { Form, Input } from 'antd';
<Form>
<Form.Item
label="用户名"
name="username"
rules={[
{
required: true,
},
]}
>
<Input placeholder="请输入用户名" />
</Form.Item>
</Form>;
不难看出,在 schema 中:
title对应的 Form.Item 中的label。dataIndex对应的 Form.Item 中的name。formItemProps的值会传递给 Form.Item 组件。fieldProps的值会传递给被 Form.Item 包裹的组件 (对这个例子来说这个组件是 Input)。
我们再来看一下第二个 schema:
{
title: "性别",
dataIndex: "gender",
valueType: "radio",
fieldProps: {
options: [
{ label: "男", value: "男" },
{ label: "女", value: "女" },
{ label: "其它", value: "其它" },
],
},
};
与第一个 schema 不同的地方在于,它多了一个 valueType 字段,很显然 SchemaForm 通过 valueType 字段渲染出了不同的组件,以这个例子来说 valueType:'radio' 对应的是一个 Radio.Group 组件,并且通过 fieldProps 给它传入了 options 属性。
这是使用 SchemaForm 的优点之一,大部分常用的组件都能通过 valueType 来渲染。
schema 部分介绍完了,我们再来看一下 表单实例 FormInstance。
表单实例 是 Antd Form 中一个比较重要的概念,通过实例中的方法,我们可以完成很多操作,比如:提交表单,重置表单,给表单赋值等。
在 SchemaForm 中,我们通过 formRef 属性来获取 表单实例。
import { useRef } from 'react';
import { ProFormInstance, SchemaForm } from 'react-admin-kit';
const formRef = useRef<ProFormInstance>() // 注意这里使用的类型定义是 ProFormInstance. 它在 antd form instance 的基础上扩展了一些方法
<SchemaForm
formRef={formRef}
>
formRef.current?.submit() // 提交
formRef.current?.resetFields() // 重置
formRef.current?.setFieldsValue() // 赋值
在后文中还会详细介绍 表单实例 中的其它一些方法。
以上就是 SchemaForm 的基本概念,看到这你已经可以开始书写一些简单的表单了 ✨。
随着你使用的不断深入,你可以不断查看下面的各种例子来了解 SchemaForm 的其它属性,相信你会越来越得心应手的。
valueType
valueType 是 schema 里的一个非常重要的字段,通过指定 valueType 就能映射出不同的表单项。常用的 valueType 有 money digit date dateRange select radio textarea 等,完整的列表见这里。当 valueType 没有指定时,默认渲染的表单项是 Input 组件。
如果 valueType 不能满足你的需求,可以使用 renderFormItem 完全自定义表单项。
自定义的组件需要满足 Form.Item 的规范,即组件能接受 value 和 onChange 属性。
{
renderFormItem: (schema, config, form) => {
return <MyComp />;
};
}
required
由于表单中设置必选的频率比较高,schema 中新增了 required 字段,作为 formItemProps: { rules: [{ required: true }]} 的简写。当然 formItemProps 的优先级更高。
表单布局
传统布局
grid 栅格模式
grid 栅格模式是把 FormItem 放入 Ant Design 的 栅格系统 中,通过传入 Row 和 Col 的属性来控制每个 FormItem 的布局。
<SchemaForm
grid
rowProps={{}}
colProps={{}}
columns=[
{
title: 'name',
colProps: {} // 更高优先级
},
{
title: 'age',
colProps: {} // 更高优先级
}
]
>
以这个组件为例,当它开启 grid 属性后,它实际上会被渲染成:
// 伪代码, 仅用于示意.
<Form>
<Row {...rowProps}>
<Col {...colProps}>
<Form.Item>
<Field />
<Form.Item>
</Col>
<Col {...colProps}>
<Form.Item>
<Field />
<Form.Item>
</Col>
</Row>
</Form>
通过栅格系统,表单项的布局将会变得更加的灵活,比如:
grid 水平方向
当开启 grid 并且 layout 为 horizontal 时,表单项的 label 宽度很可能会不一致。如下所示:
有许多方法能让 label 宽度统一。比如给它设定一个最小宽度:
或者给每个表单的 label 单独指定宽度。
labelCol是 Antd Form 的一个属性。同 Col 组件,可以传入{span: 8}或者{flex: 0 0 30%}等属性。
labelCol是以其 所在表单项 的宽度作为基值(24 份)来进行后续计算的。{span: 8}代表 label 占 所在表单项 的宽度的 8 份。{flex: 0 0 30%}代表 label 占 所在表单项 的宽度的 30%。
空白占位
需要强制换行时 可用空白占位.
表单操作
只读模式
通过 readonly 属性或者 schema 上的 readonly 属性可以设置只读模式. 只读模式有以下几个注意点:
- 只读模式下的自定义显示用
render方法, 而不是renderFormItem. - 空白占位可以用
render方法返回 null 来实现.render: () => null.
💡 Rakjs 扩展了只读模式下 render 函数的第二个参数 record. 这个 record 里包含了表单里的所有值, 提高了实用性.
只读表格模式
只读模式还能转化成表格的形式,类似 Antd Descriptions 组件。
表单项联动
初始值和表单项赋值
- [是否显示用户] 初始值为否。
- 点击赋值按钮后显示为是。
- 点击重置按钮后显示为否。
提交按钮 submitter
submitter 属性默认为 false. 开启后可自动生成提交按钮.
还可以给生成的按钮传递属性.
只读与编辑切换
下面模拟演示两个真实场景:
1. 模拟一个表单页的回显
2. 只读表单项的依赖显示