在V1版本解决在MST中搭建静态表单之后,V2版本重写了整体架构,改变了Schema的格式,新支持了一层深度的动态表单,并且优化了校验和初始化逻辑,支持更多场景。
链接
安装
npm i mst-form-type -S
注意:需要自行安装mobx-state-tree的5.0.0以上版本。
使用
typescript
import createForm from 'mst-form-type'
const dynamicForm: FormSchema = {
static: [
{
id: 'name',
default: '',
validator: 'required',
},
{
id: 'des',
default: '',
},
],
dynamic: [
{
id: 'price', // group id
limit: 100,
schema: [
{
id: 'itemName',
default: '',
validator: 'required',
},
{
id: 'itemPrice',
default: 10,
},
],
default: [
{
itemName: 'itemName1',
itemPrice: 5,
},
{
itemName: 'itemName2',
itemPrice: 20,
},
],
onAdd: i => {
console.log('add', i)
},
onRemove: i => {
console.log('remove', i)
},
onEdit: key => {
console.log('edit', key)
},
},
],
}
// render dynamic fields
model.dynamicForm['price'].fields.map(fields => ({ ... }))
// field action
model.dynamicForm.onAdd('price') // this will use field default value in schema
model.dynamicForm.onRemove('price', fields.id)
// form action
model.dynamicForm.submit()
model.dynamicForm.reset()
model.dynamicForm.clear('price') // this will clear all dynamic fields, including default ones
const Main = types.model('Main', {
form: createForm(schema, 'name?')
...
})
// change field value
model.form.setValue({ key, value })
// change dynamic field value
model.form.setDynamicValue({ groupId, id, key, value })
// submit form
model.form.submit() => { key1: value1, key2: value2, ... }
APIs
mst-form-type通过default export提供了一个函数接受schema,生成新的type,将该form相关的伴随状态都包裹在了新type之内。
V2改变了Schema的格式,新的Schema直接区分了静态field和动态field,并统一了field的Schema,让Schema的定义更加清晰。针对动态field的需要,使用新的key定义增加的功能。
schema
typescript
// Old
type schema = {
[key: string]: {
default: string | number
validator?: 'required' | ((...args: any[]) => boolean) | RegExp | undefined | null
}
}
// New
export type TValidator = 'required' | ((...args: any[]) => boolean) | RegExp | undefined | null
export type TValue = string | boolean | number | Record<string, string> | Array<any>
interface FieldSchema {
id: string
type?: 'string' | 'number' | 'object' | 'array' | 'boolean'
default: TValue
validator?: TValidator
msg?: string
}
interface DynamicFields {
id: string
limit: number
schema: FieldSchema | FieldSchema[]
default: Array<Record<string, TValue>>
onAdd?: (arg) => any
onRemove?: (id: string) => any
onEdit?: (key: string) => void
}
interface FormSchema {
static: FieldSchema[]
dynamic?: DynamicFields[]
}
在不需要动态field的情况下,V1的Schema格式继续支持,但是底层的逻辑是在没有'dynamic'这个 key的情况下,把所有的key都放到'static'的key中,并用原本的key作为field id。所以,如果不是遗留代码,推荐直接使用新的Schema。
注意,虽然value支持多种类型,但由于传给API时都会转化成字符串,建议直接在value中使用字符串
props
form type上的props没有增加,只是把'internalStatus'改为了'_internalStatus'。
在底层新增了field type。在V2中,每个field type的instance会持有自己的状态,例如value,validator,status等。这些状态不再存在于form type的instance中。如果需要,可以获取到field实例,使用field上面的props。
动态field还增加了一层group type,在group type中包含多组动态field。渲染时需要通过groupId.fields按数组进行渲染,数组元素为一组field实例。同时group type中会承载这组动态field的相关属性和回调方法。还可以通过group的size prop和limit prop,获取当前动态field的数量和最多限制。
actions
除了V1的action,V2主要增加了针对动态field的action,并且移除了initVal这个action,下面分别介绍:
注意,一些action是在group type上的,在form type上会调用失败
getValues()
存在于group type,获取当前所有动态field的值,以数组形式返回。
setDynamicValue({ groupId, id, key, value })
存在于form type,设定单一特定动态field的值,本质上通过groupId找到对应的group instance后,调用其上的editFields实现。
onAdd(groupId, item)
存在于form type,为指定的group增加一组新的动态field,内容为item参数,如果不传,则使用schema中field设定的默认值。本质上通过groupId找到对应的group instance后,调用其上的addFields实现。
onRemove(groupId, itemId)
存在于form type,删除指定的group中的id为itemId的动态field。本质上通过groupId找到对应的group instance后,调用其上的removeFields实现。
onEdit(groupId, itemId, key, value)
存在于form type,修改指定的group中的id为itemId的动态field的value,和setDynamicValue的作用完全一样。本质上通过groupId找到对应的group instance后,调用其上的editFields实现。
clear()
存在于form type,清除所有的动态field,不光是值,只清除值用reset()。