增删子表单
- github: github.com/easy-page/e…
- 文档站官网:easy-page.github.io/easy-page-d…
- 文档站 github: github.com/easy-page/e…
我们常常会在表单里嵌入持续增加的子表单:
- 可以添加子表单
- 可以删除子表单
传统的写法,往往会耗费很多精力处理状态管理的事情,而现在,只需要一个 API 即可:
createChildForm
案例
创建子表单基本信息
首先,我们创建一个子表单的信息:
- 创建一个子表单里的字段:
testChild
(/childForm/fields/testChild.ts)
import { nodeUtil } from '@easy-page/antd-ui';
export const testChild = nodeUtil.createField('test1', '测试1', {});
- 放入子表单页面信息:
import { PageUtil } from '@easy-page/antd-ui';
import { testChild } from './fields';
const pu = new PageUtil({ pageId: 'xx' })
pu.addFields([testChild]);
export const childFormInfo = pu.getPageInfo()
创建子表单容器、放入 childFormInfo 信息
- 我们通过
createChildForm
创建一个子表单容器,放入子表单页面。
const prefix = 'child-form';
const defaultId = generateId(prefix);
export const childFormField = nodeUtil.createChildForm<ChildFormState>(
'cc',
{
value: {
childForms: [{ id: defaultId, label: '子活动' }],
choosedItemId: defaultId,
},
childFormContainer: ({ setChildFormRef, value, onChange }) => {
const { childForms, choosedItemId } = value;
return (
<Tabs
activeKey={choosedItemId}
onChange={(val) =>
onChange({
...(value || ({} as ChildFormState)),
choosedItemId: val,
})
}
items={childForms.map((e, idx) => ({
label: `子表单${idx}`,
id: e.id,
key: e.id,
children: (
<EasyPage<ChildFormState>
{...childFormInfo}
pageType="form"
components={DEFAULT_COMPONENTS}
setFormUtil={(ref) => setChildFormRef(ref, e.id)}
/>
),
}))}
></Tabs>
);
},
},
{}
);
如上展示:
- 我们通过:
createChildForm
创建了子表单 - 我们通过:
value
定义,给子表单默认了一个表单选项。 - 我们通过:
childFormContainer
创建了子表单的布局,采用Tabs
布局 - 我们通过:
items
属性,传递了子表单组件EasyPage
,组件内容为我们刚才定义的:childFormInfo
信息
到此,我们就完成了子表单的基础信息创建:容器、页面结构。
:::tips
需要注意的是:onChange
的处理以及:setFormUtil
的传递,是必须的,大家写的时候可参考上述示例使用。
:::
增加子表单、删除子表单功能
- 我们通过
onEdit
快速完成子表单增删。
childFormContainer: ({
setChildFormRef,
onAdd,
onRemove,
value,
onChange,
}) => {
const { childForms, choosedItemId } = value;
return (
<Tabs
onEdit={(e, action) => {
if (action === 'add') {
onAdd();
} else if (action === 'remove') {
onRemove(e as string);
}
}}
...
></Tabs>
可以发现,我们只是添加了: onEdit
就实现了效果,其他我们不用操心
数据提交处理
export const childFormField = nodeUtil.createChildForm<ChildFormState>(
'cc',
{
value: {
childForms: [{ id: defaultId, label: '' }],
choosedItemId: defaultId,
},
...,
postprocess({ value }) {
const { formUtils, childForms } = value;
return {
activities: childForms.map((e) => {
const util = formUtils?.[e.id];
const data = util?.getFormData();
return data;
}),
};
},
})
我们增加了 postprocess
定义,通过 value
里的 formUtils
获取了完整的字表单数据,并返回。
子表单验证
export const childFormField = nodeUtil.createChildForm<ChildFormState>(
'cc',
{
value: {
childForms: [{ id: defaultId, label: '' }],
choosedItemId: defaultId,
},
...,
validate: async ({ value }) => {
const results = await validateAllChildForm(value);
const hasError = results.find((e) => Boolean(e.errors));
return { success: !hasError };
},
})
我们增加了:validate
方法,当最外层表单调用验证的时候,会执行此表单这个方法,我们通过:validateAllChildForm
就验证完了所有子表单。
数据回填
export const childFormField = nodeUtil.createChildForm<ChildFormState>(
'cc',
{
value: {
childForms: [{ id: defaultId, label: '' }],
choosedItemId: defaultId,
},
...,
preprocess({ defaultValues }) {
const acts = defaultValues.activities || [];
const defaultActId1 = generateId(prefix);
return {
childForms: acts.map((e, idx: number) => ({
label: `子活动${idx}`,
id: idx === 0 ? defaultActId1 : generateId(prefix),
})),
choosedItemId: defaultActId1,
};
},
})
回填的时候,我们只是增加了:preprocess
方法,将子表单的数量和 ID 基本信息做了处理。
接着,我们在:childFormContaienr
子表单处,获取相应的默认值即可。
childFormContainer: ({
frameworkProps: { store },
...
}) => {
const { childForms, choosedItemId } = value;
const defaultValues = store.getDefaultValues();
return (
<Tabs
...
items={childForms.map((e, idx) => {
const defaultValue = defaultValues?.activities?.[idx];
return {
label: `子表单${e.id}`,
id: e.id,
key: e.id,
children: (
<EasyPage<ChildFormState>
{...childFormInfo}
defaultValues={defaultValue}
components={DEFAULT_COMPONENTS}
setFormUtil={(ref) => setChildFormRef(ref, e.id)}
/>
),
}
})}
></Tabs>
);
},
-
我们通过:
framworkprops.store
获取全部默认值:store.getDefaultValues()
-
我们根据提交时的数据 key:
activities
和表单 idx 获得对应表单默认值:const defaultValue = defaultValues?.activities?.[idx];
-
最后放到 EasyPage 上即可:
<EasyPage<ChildFormState> {...childFormInfo} defaultValues={defaultValue} pageType="form" components={DEFAULT_COMPONENTS} setFormUtil={(ref) => setChildFormRef(ref, e.id)} />