add form submit example

This commit is contained in:
hufeixiong
2021-08-05 15:13:57 +08:00
parent 6323b9419f
commit 90a4ce0285
8 changed files with 234 additions and 13 deletions

View File

@@ -0,0 +1,21 @@
---
title: 表单验证提交思路
sTitle: 常见问题
order: 20
---
表单验证提交有非常多的做法,因为数据全部是联通的,或者直接写个表单组件也可以。
在不使用表单组件时,简单的做法是为每个输入组件做个验证函数与提交函数。
这样是否验证就取决于用户的选取,而抛出的输入可以让用户选择放到哪,并由用户去命名变量。
在点击提交按钮时调用所有组件的验证函数与提交函数使其抛给上下文再通过上下文聚合函数聚合成对象最后可以通过发送函数发送给对应后端从而完成整个流程。你可以在example中试下这个demo。
如果操作人员能看懂后端提供的接口文档,那么就可以让操作人员自己通过命名来拼出后端想要的字段。
如果不需要文档,那么某些值也可以在开发时写死。
另外的做法是可以专门写个提交按钮,固定了参数,以及部分规则,比如规定在页面中的所有表单都会被收集提交。
那么我们可以利用数据源将所有表单输出内容自动提交给数据源最后的提交按钮按数据源规定格式的key提取发送给后端。

View File

@@ -2,7 +2,7 @@
* @Author: yehuozhili * @Author: yehuozhili
* @Date: 2021-08-03 10:45:06 * @Date: 2021-08-03 10:45:06
* @LastEditors: yehuozhili * @LastEditors: yehuozhili
* @LastEditTime: 2021-08-03 10:45:07 * @LastEditTime: 2021-08-05 14:35:49
* @FilePath: \dooringx\packages\dooringx-example\src\plugin\formComponents\switch.tsx * @FilePath: \dooringx\packages\dooringx-example\src\plugin\formComponents\switch.tsx
*/ */
import React, { useMemo, memo } from 'react'; import React, { useMemo, memo } from 'react';
@@ -25,10 +25,10 @@ const MSwitch = (props: MSwitchProps) => {
const store = props.config.getStore(); const store = props.config.getStore();
return ( return (
<Row style={{ padding: '10px 20px' }}> <Row style={{ padding: '10px 20px' }}>
<Col span={6} style={{ lineHeight: '30px' }}> <Col span={8} style={{ lineHeight: '30px' }}>
{(option as any)?.label || '文字'} {(option as any)?.label || '文字'}
</Col> </Col>
<Col span={18}> <Col span={16}>
<Switch <Switch
checked={props.current.props[(option as any).receive] || ''} checked={props.current.props[(option as any).receive] || ''}
onChange={(checked) => { onChange={(checked) => {

View File

@@ -2,7 +2,7 @@
* @Author: yehuozhili * @Author: yehuozhili
* @Date: 2021-07-07 14:31:20 * @Date: 2021-07-07 14:31:20
* @LastEditors: yehuozhili * @LastEditors: yehuozhili
* @LastEditTime: 2021-08-03 10:45:52 * @LastEditTime: 2021-08-05 15:10:23
* @FilePath: \dooringx\packages\dooringx-example\src\plugin\formTypes.ts * @FilePath: \dooringx\packages\dooringx-example\src\plugin\formTypes.ts
*/ */
export interface FormBaseType { export interface FormBaseType {
@@ -10,14 +10,12 @@ export interface FormBaseType {
} }
export interface FormInputType extends FormBaseType { export interface FormInputType extends FormBaseType {
label: string; label: string;
text: string;
} }
export interface FormActionButtonType {} export interface FormActionButtonType {}
export interface FormAnimateControlType {} export interface FormAnimateControlType {}
export interface FormSwitchType extends FormBaseType { export interface FormSwitchType extends FormBaseType {
label: string; label: string;
value: boolean;
} }
export interface FormMap { export interface FormMap {
input: FormInputType; input: FormInputType;

View File

@@ -2,9 +2,41 @@
* @Author: yehuozhili * @Author: yehuozhili
* @Date: 2021-07-07 14:22:51 * @Date: 2021-07-07 14:22:51
* @LastEditors: yehuozhili * @LastEditors: yehuozhili
* @LastEditTime: 2021-07-09 13:52:51 * @LastEditTime: 2021-08-05 14:53:12
* @FilePath: \dooringx\packages\dooringx-example\src\plugin\functionMap\index.ts * @FilePath: \dooringx\packages\dooringx-example\src\plugin\functionMap\index.ts
*/ */
import { FunctionCenterType } from 'dooringx-lib/dist/core/functionCenter'; import { FunctionCenterType } from 'dooringx-lib/dist/core/functionCenter';
export const functionMap: FunctionCenterType = {}; export const functionMap: FunctionCenterType = {
: {
fn: (ctx, next, _config, args) => {
const arr = args['_sk'];
const key = args['_r'];
const param: Record<string, any> = {};
arr.forEach((v: string) => {
param[v] = ctx[v];
});
ctx[key] = param;
console.log(ctx);
next();
},
config: [
{
name: '输入要获取的上下文',
data: ['ctx'],
options: {
receive: '_sk',
multi: true,
},
},
{
name: '输入要生成的上下文',
data: ['ctx'],
options: {
receive: '_r',
multi: false,
},
},
],
},
};

View File

@@ -2,7 +2,7 @@
* @Author: yehuozhili * @Author: yehuozhili
* @Date: 2021-02-27 21:33:36 * @Date: 2021-02-27 21:33:36
* @LastEditors: yehuozhili * @LastEditors: yehuozhili
* @LastEditTime: 2021-08-03 23:21:01 * @LastEditTime: 2021-08-05 10:54:22
* @FilePath: \dooringx\packages\dooringx-example\src\plugin\index.tsx * @FilePath: \dooringx\packages\dooringx-example\src\plugin\index.tsx
*/ */
@@ -12,6 +12,7 @@ import { ContainerOutlined, HighlightOutlined } from '@ant-design/icons';
import commandModules from './commanderModules'; import commandModules from './commanderModules';
import { functionMap } from './functionMap'; import { functionMap } from './functionMap';
import { Formmodules } from './formComponentModules'; import { Formmodules } from './formComponentModules';
import InputCo from './registComponents/inputCo';
const LeftRegistMap: LeftRegistComponentMapItem[] = [ const LeftRegistMap: LeftRegistComponentMapItem[] = [
{ {
@@ -21,6 +22,12 @@ const LeftRegistMap: LeftRegistComponentMapItem[] = [
displayName: '按钮', displayName: '按钮',
urlFn: () => import('./registComponents/button'), urlFn: () => import('./registComponents/button'),
}, },
{
type: 'basic',
component: 'input',
img: 'icon-anniu',
displayName: '输入框',
},
]; ];
export const defaultConfig: Partial<InitConfig> = { export const defaultConfig: Partial<InitConfig> = {
@@ -38,7 +45,9 @@ export const defaultConfig: Partial<InitConfig> = {
customRender: <div></div>, customRender: <div></div>,
}, },
], ],
initComponentCache: {}, initComponentCache: {
input: { component: InputCo },
},
rightRenderListCategory: [ rightRenderListCategory: [
{ {
type: 'style', type: 'style',

View File

@@ -2,7 +2,7 @@
* @Author: yehuozhili * @Author: yehuozhili
* @Date: 2021-07-07 14:35:38 * @Date: 2021-07-07 14:35:38
* @LastEditors: yehuozhili * @LastEditors: yehuozhili
* @LastEditTime: 2021-08-03 11:01:06 * @LastEditTime: 2021-08-05 15:10:31
* @FilePath: \dooringx\packages\dooringx-example\src\plugin\registComponents\button.tsx * @FilePath: \dooringx\packages\dooringx-example\src\plugin\registComponents\button.tsx
*/ */
@@ -102,14 +102,12 @@ const MButton = new ComponentItemFactory(
createPannelOptions<FormMap, 'input'>('input', { createPannelOptions<FormMap, 'input'>('input', {
receive: 'text', receive: 'text',
label: '文字', label: '文字',
text: 'yehuozhili',
}), }),
], ],
fn: [ fn: [
createPannelOptions<FormMap, 'switch'>('switch', { createPannelOptions<FormMap, 'switch'>('switch', {
receive: 'op1', receive: 'op1',
label: '改变文本函数', label: '改变文本函数',
value: false,
}), }),
], ],
animate: [createPannelOptions<FormMap, 'animateControl'>('animateControl', {})], animate: [createPannelOptions<FormMap, 'animateControl'>('animateControl', {})],

View File

@@ -0,0 +1,161 @@
/*
* @Author: yehuozhili
* @Date: 2021-08-05 10:50:57
* @LastEditors: yehuozhili
* @LastEditTime: 2021-08-05 15:10:46
* @FilePath: \dooringx\packages\dooringx-example\src\plugin\registComponents\inputCo.tsx
*/
import { Input } from 'antd';
import React, { useState } from 'react';
import { ComponentItemFactory, createPannelOptions, UserConfig } from 'dooringx-lib';
import { FormMap } from '../formTypes';
import { IBlockType } from '../../../../dooringx-lib/dist/core/store/storetype';
import Store from '../../../../dooringx-lib/dist/core/store';
import { useEffect } from 'react';
interface InputProps {
data: IBlockType;
context: string;
store: Store;
config: UserConfig;
}
const InputTemp = (pr: InputProps) => {
const { props } = pr.data;
const data = pr.data;
const dataCenter = pr.config.getDataCenter();
const eventCenter = pr.config.getEventCenter();
const [value, setValue] = useState('');
const [err, setErr] = useState('');
useEffect(() => {
let unregist = () => {};
if (props.op1) {
const functionCenter = eventCenter.getFunctionCenter();
unregist = functionCenter.register(
`${pr.data.id}+验证已填函数`,
async (_ctx, next, _config, _args: any, _eventList, _iname) => {
if (value === '') {
setErr(props.warnning);
} else {
setErr('');
next();
}
},
[
{
name: '验证已填函数',
data: [],
options: {
receive: '_changeval',
multi: false,
},
},
]
);
}
return () => {
unregist();
};
}, [value, props.warnning, props.op1]);
useEffect(() => {
let unregist = () => {};
if (props.op2) {
const functionCenter = eventCenter.getFunctionCenter();
unregist = functionCenter.register(
`${pr.data.id}+获取输入数据`,
async (ctx, next, _config, args: any, _eventList, _iname) => {
const key = args['_changeval'][0];
ctx[key] = value;
next();
},
[
{
name: '获取数据至上下文',
data: ['ctx'],
options: {
receive: '_changeval',
multi: false,
},
},
]
);
}
return () => {
unregist();
};
}, [value, props.op2]);
return (
<div
style={{
display: 'inline-block',
zIndex: data.zIndex,
width: data.width,
height: data.height,
overflow: 'hidden',
}}
>
<Input
value={value}
type={props.type}
placeholder={props.placeholder}
style={{ height: 'calc( 100% - 20px )' }}
onChange={(e) => {
setValue(e.target.value);
}}
></Input>
<div style={{ height: '20px', color: 'red', fontSize: '12px' }}>{err}</div>
</div>
);
};
const InputCo = new ComponentItemFactory(
'input',
'输入组件',
{
style: [
createPannelOptions<FormMap, 'input'>('input', {
receive: 'placeholder', //用于发送回的props必传 ,跨组件传递需要指定额外字
label: '文本',
}),
createPannelOptions<FormMap, 'input'>('input', {
receive: 'warnning', //用于发送回的props必传 ,跨组件传递需要指定额外字
label: '验证消息',
}),
],
fn: [
createPannelOptions<FormMap, 'switch'>('switch', {
receive: 'op1',
label: '开启验证函数',
}),
createPannelOptions<FormMap, 'switch'>('switch', {
receive: 'op2',
label: '开启获取文本函数',
}),
],
animate: [createPannelOptions<FormMap, 'animateControl'>('animateControl', {})],
actions: [createPannelOptions<FormMap, 'actionButton'>('actionButton', {})],
},
{
syncList: ['synckey'],
props: {
type: 'text',
placeholder: '请输入',
warnning: '输入框不可为空',
op1: false,
op2: false,
},
width: 200,
height: 55,
},
(data, context, store, config) => {
return <InputTemp data={data} context={context} store={store} config={config}></InputTemp>;
},
true
);
export default InputCo;

View File

@@ -151,6 +151,8 @@ MIT
## Todo ## Todo
动画部分重构
函数部分重构 函数部分重构