NewbieForm

表单组件

通过 JSON 配置生成表单,并集成表单验证,获取数据,提交数据等功能。

Version: 1.0.0

Props

Prop nameDescriptionTypeValuesDefault
title表单标题,Card 模式下生效string-""
data表单数据,用于初始化表单,并会进行 Watchobject|string-""
autoLoad是否自动加载
true 表示自动加载数据
Array,String 表示会对 extraData 数据中的相关字段进行非空验证,不为空再加载数据
boolean|array|string-true
fetchUrl获取表单数据的 URLstring-""
extraData额外的数据,在提交时会合并到表单数据中并一起提交object-{}
submitUrl提交数据 URLstring-""
submitButtonText提交按钮文字string-"保存"
submitConfirmText提交确认提示内容string-""
closable是否显示关闭按钮boolean-true
closeButtonText关闭按钮文字string-"关闭"
closeButtonFirst是否将关闭按钮放在提交按钮前面boolean-false
hideButtons是否隐藏按钮boolean-false
disabled是否禁用表单boolean-false
readonly是否只读boolean-false
submitDisabled是否禁用提交按钮boolean-false
dividerProps当有分割线时,原生分割线配置open in new windowobject-{}
columns表单布局,默认为单列,当为多列时,按 24 栅格布局
如:columns: [12, 12]
array-[24]
fixedColumns如有 fixed 列,默认 fixed 列的宽度为 6,可自定义number-6
cardSizeCard 的大小stringsmall, default"small"
cardWrapper是否用 Card 包裹boolean-true
form表单配置,见表单项配置array|func-function() {
return []
}
afterFetchedfetch 返回数据处理函数
@return {Object} 返回处理后的数据,将用于初始化表单
func-null
beforeSubmit
@typedef {Object} ExposedFormData
@property Format 后的表单数据
@property 原生的表单数据
@params undefined
@return {Boolean|Object} return false 会阻止提交操作,return Object 会替换提交的数据
func-null
close点击关闭时的动作func-null
afterSubmit提交成功后的回调func-null
formProps原生的 Fromopen in new window 配置object-{}

Events

Event namePropertiesDescription
success

详细参数

FormItemConfig 表单项配置

Prop nameDescriptionTypeValuesDefault
key数据库关联名称string-""
title显示的 Label 名字string-""
type支持的组件类型string见下表"input"
options组件选项array | func-[]
placeholder组件里的提示string-""
helpform item 里的提示string | func-""
width组件宽度string-""
style样式string-""
class类名string-""
init初始化函数,用于初始化表单项的值: init({ submitForm, value })func--
beforeSubmit在提交前修改表单项的值,该函数会在 NewbieForm 的 beforeSubmit 之前调用: beforeSubmit({ submitForm, value })func--
readonly是否只读boolean-false
required是否必填, 函数用法见下方FAQboolean | func-false
disabled组件不可编辑状态, 函数用法见下方FAQboolean | func-false
hidden组件是否隐藏, 函数用法见下方FAQboolean | func-false
optional表单项是否开启后才可以输入, 用法见下方FAQboolean | Array-false
match支持根据条件返回不同的配置进行动态渲染, 用法见下方FAQFunction--
columnIndex渲染在哪一列number | string-
break是否新起一行,如果为 String 则以 Divider 分割boolean | string-false
defaultProps组件的配置object-{}
formItemProps同原生 FormItemopen in new window 配置, 并可以直接使用 slots 属性定义 FormItem 的 slotobject-{}
defaultValue默认值any-""
children子组件配置array<FormItemConfig>--
cellProps子组件渲染的单元格配置open in new windowobject--
customRender自定义渲染函数func--

FormItemConfig.type 支持组件类型

TypeDescription
input输入框
select选择框
remote远程检索
tree-select树状选择
date日期选择
time时间选择
switch开关
radio单选
checkbox多选
tag标签输入
address地址选择
cascade级联选择
number数字
htmlHTML 内容
uploader文件上传
editor富文本编辑
text文本显示
group数组组件,用法见示例
slot自定义插槽

FormItemConfig.type.remote 远程搜索特有参数

Prop nameDescriptionTypeValuesDefault
keyword检索时的关键词string-"keyword"
url检索的 urlstring--
method检索的方法stringget, post"get"
params检索时的附带参数object-{}
onSearch服务器返回参数的处理函数func-null

方法

名称参数说明
isInitializing(loading:boolean) => void设置表单加载状态
reset() => void重置表单
getFormStandalone() => Object获取一份表单值的复制
getForm() => Object获取表单值
setForm({key: value}) => void设置表单一项或多项的值
isDirty() => boolean表单是否被污染

Provider

名称参数说明
formatObject用于格式化提示的表单数据, 同useFormFormatopen in new window
afterFetched(response) => ObjectFunction表单数据获取数据后的回调函数, 参数为请求的 response
<NewbieProvider :form="{format: {boolean: true, date: 'YYYY-MM-DD'}}" />

FAQ

如果需要表单使用自定义组件,如何配置?

使用 formItem.typeslot 或者是 formItem.customRender 进行自定义组件的渲染 ,示例如下:

  1. 使用 slot 自定义组件
<NewbieForm>
	<template #input="{submitForm}">
		<a-form-item>blabla</a-form-item>
	</template>
</NewbieForm>
{
	key: "input",
	title: "自定义组件",
	type: "slot",
}
  1. 使用 customRender 自定义组件
{
	key: "input",
	title: "自定义组件",
	customRender({submitForm, item}){
	    return h("div", {}, "whatever you want")
	}
}

如何动态控制表单项是否可见/是否必填/是否禁用?

使用 formItem.hiddenformItem.requiredformItem.disabled 控制表单项是否可见/是否必填/是否禁用,这三个参数均可直接传入一个 boolean 值,也可以传入一个函数,函数接收一个参数 submitForm,返回一个 boolean 值,示例如下:

{
	key: "input",
	title: "输入 Input",
	hidden: (submitForm) => submitForm.other_item === 'make me hidden', //为 true 时当前表单项隐藏
	required: (submitForm) => submitForm.other_item ==='make me required', //为 true 当前表单项必填
	disabled: (submitForm) => submitForm.other_item ==='make me disabled', //为 true 当前表单项禁用
}

Group 数组组件如何使用?

Group 数组组件, 其 typegroup, 并且使用 children 对象数组对子表单进行定义, 定义方式与普通表单项一致, 其 value 为一个对象数组, 组件内部自带基础的 编辑, 新增, 删除功能, 支持通过 childrenOperations 属性传入自定义操作, 示例如下:

{
	key: "data_sources",
	title: "数据源",
	type: "group",
	childrenOperations: [{
        name: "推荐",
        props: {
            icon: h(LikeOutlined),
            size: "small",
        },
        action() {},
    }],
	children: [
		{
			title: "数据",
			type: "tree-select",
			key: "category_id",
			width: 300,
			options: [
				{
				}
			}
		}
	]

FormItem 的 match 如何使用?

当一个字段需要根据不同的条件进行动态渲染时,match 方法以 submitForm 为参数,返回一个选项配置, 该配置将与 FormItem 本身的属性进行合并后重新进行渲染, 也就是相同的属性可以直接定义在 FormItem 上, 而不需要再定义在 match 上, 相同属性将以 match 的配置为准 。示例:

{
    key: "match",
    title: "匹配 Match",
    columnIndex: 1,
    match(submitForm) {
       if (submitForm.input === "1") {
            return { type: "input", placeholder: "这只能一句话" }
       } else {
            return { type: "textarea", placeholder: "这里可以是一段话" }
       }
    },
}

FormItem 的 optional 如何使用?

有时候一些限制项, 譬如 是否限制人数, 需要先选择 , 如果选择之后再填写需要限制的具体人数, 如果 optionaltrue, 则会渲染一个 Switch, 当用户选择以后, 才会展示定义的输入组件(本示例中为 number), 可以填写具体的限制人数. optional 参数也可以传一个长度为 2 的数组, 如: ['限制', '不限制'], 该参数将做为 SwitchcheckChildrenunCheckChildren

注意: 如果 optional 搭配的输入组件为 number, 那不开启的时候, 该组件会将默认的 value 设置为 0

{
	key: "limit_num",
	title: "限制人数",
	type: "number",
	optional: true,
}

如何自定义 FromItem 的属性/slot

FormItem 中的 fromItemProps 与原生 FormItemopen in new window 的配置相同, 并支持直接传入 slots 对象, 用于自定义 FormItemslot,示例如下:

{
    colon: true,
	slots: {
		tooltip: () => h("div", {}, "whatever you want")
	}
}

示例


测试表单

<template>
	<NewbieForm :form="getForm()" :columns="[24]" card-wrapper title="测试表单" :closable="false">
		<template #prepend>
			<p>Prepend</p>
		</template>
		<template #append>
			<p>Append</p>
		</template>
	</NewbieForm>
</template>

<script setup>
import { h } from "vue"
import { NewbieForm } from "jobsys-newbie"

const getForm = () => {
	return [
		{
			key: "limit_num",
			title: "限制人数 Optional",
			type: "number",
			optional: ["限制", "不限制"],
		},
		{
			key: "address",
			title: "地址 Address",
			type: "address",
		},
		{
			key: "text",
			title: "文本 Text",
			type: "text",
			defaultValue: "默认值",
		},
		{
			key: "input",
			title: "输入 Input",
			columnIndex: 1,
		},
		{
			title: "数据源",
			key: "data_sources",
			type: "group",
			children: [
				{
					title: "数据",
					type: "tree-select",
					key: "category_id",
					width: 300,
					options: [
						{ id: 1, name: "test", children: [{ id: 2, name: "child1" }] },
						{ id: 3, name: "test2" },
					],
					defaultProps: {
						multiple: true,
						treeNodeFilterProp: "name",
						fieldNames: {
							children: "children",
							label: "name",
							value: "id",
						},
					},
				},
				{
					title: "是否分页",
					key: "is_pagination_required",
					type: "switch",
					defaultValue: true,
				},
			],
		},
		{
			key: "textarea",
			title: "长文本 Textarea",
			type: "textarea",
			break: "一个新的行",
		},
		{
			key: "password",
			title: "密码 Password",
			type: "password",
			columnIndex: 3,
		},
		{
			key: "editor",
			title: "富文本 Editor",
			type: "editor",
			columnIndex: [0, 1],
		},
		{
			key: "html",
			title: "HTML",
			type: "html",
			defaultValue: "<p style='color: #ff0000; margin: 0;'>插播一条 HTML</p>",
		},
		{
			key: "number",
			title: "数字 Number",
			type: "number",
			columnIndex: 1,
		},
		{
			key: "radio",
			title: "单选 Radio",
			type: "radio",
			options: ["选项1", "选项2"],
			defaultValue: "选项1",
		},
		{
			key: "checkbox",
			title: "多选 Checkbox",
			type: "Checkbox",
			options: ["选项1", "选项2"],
			defaultValue: ["选项1"],
			columnIndex: 1,
		},
		{
			key: "address",
			title: "地址 Address",
			type: "address",
		},
		{
			key: "cascade",
			title: "级联选择器 Cascader",
			type: "cascade",
			columnIndex: 1,
			options: [
				{
					value: "zhejiang",
					label: "Zhejiang",
					children: [
						{
							value: "hangzhou",
							label: "Hangzhou",
							children: [
								{
									value: "xihu",
									label: "West Lake",
								},
							],
						},
					],
				},
				{
					value: "jiangsu",
					label: "Jiangsu",
					children: [
						{
							value: "nanjing",
							label: "Nanjing",
							children: [
								{
									value: "zhonghuamen",
									label: "Zhong Hua Men",
								},
							],
						},
					],
				},
			],
		},
		{
			key: "switch",
			title: "开关 switch",
			type: "switch",
			options: ["开", "关"],
		},
		{
			key: "date",
			title: "日期 Date",
			type: "date",
			defaultProps: {
				onChange: (val) => {
					console.log(val)
				},
			},
		},
		{
			key: "time",
			title: "时间 Time",
			type: "time",
			defaultProps: {
				onChange: (val) => {
					console.log(val)
				},
			},
		},
		{
			key: "tag",
			title: "标签 Tag",
			type: "tag",
		},
		{
			key: "remote",
			title: "远程检索 Remote",
			type: "remote",
			url: "https://suggest.taobao.com/sug",
			keyword: "q",
			onSearch: (res) => {
				return res.result.map((item) => {
					return {
						label: item[0],
						value: item[1],
					}
				})
			},
		},
		{
			key: "select",
			title: "选择 Select",
			type: "select",
			options: [
				{
					label: "选项1",
					value: "1",
				},
				{
					label: "选项2",
					value: "2",
				},
			],
		},
		{
			key: "tree-select",
			title: "树型选择 TreeSelect",
			type: "tree-select",
			options: [
				{
					label: "parent",
					value: "parent",
					children: [
						{
							label: "parent 1",
							value: "parent 1",
							children: [
								{
									label: "parent 1-0",
									value: "parent 1-0",
									children: [
										{
											label: "my leaf",
											value: "leaf1",
										},
										{
											label: "your leaf",
											value: "leaf2",
										},
									],
								},
								{
									label: "parent 1-1-1",
									value: "parent 1-1-1",
								},
							],
						},
						{
							label: "parent 1-1",
							value: "parent 1-1",
						},
					],
				},
			],
		},
	]
}
</script>

开发

如何添加一个新的表单组件?

  1. 添加初始化值的处理 form/utils/initItemDefaultValue
  2. 编写组件主体 form/compeonnts/NewComponent.jsx
  3. 将组件添加到 form/components/index.js
  4. FormItem 中添加新的类型渲染 form/components/FormItem.jsx
Last Updated:
Contributors: sinceow