Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: bind 能力增强 #1556

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 104 additions & 2 deletions docs/form-render/advanced-bind.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ group:
order: 1
---

# bind
<!-- # bind

类型:string | string[] | false

Expand Down Expand Up @@ -255,9 +255,111 @@ const Demo = () => {

export default Demo;

```
``` -->



## 进阶
- 对象嵌套情况, bind 要写绝对路径
- List 组件嵌套情况,bind 路径从 List 嵌套的子节点开始写
```jsx
import React from 'react';
import { Button } from 'antd';
import FormRender, { useForm } from 'form-render';

const delay = ms => new Promise(res => setTimeout(res, ms));

const schema = {
type: 'object',
properties: {
obj: {
title: '对象',
type: 'object',
description: '对象嵌套 bind 要写决定路径',
// bind: 'root',
properties: {
a: {
title: '日期',
widget: 'input',
},
b: {
title: '日期',
widget: 'input',
},
}
},
obj2: {
title: '对象',
type: 'object',
description: '对象嵌套 bind 要写决定路径',
bind: 'parent',
properties: {
c: {
title: '日期',
widget: 'input',
bind: 'obj.c'
},
d: {
title: '日期',
widget: 'input',
},

obj3: {
title: '对象',
type: 'object',
description: '对象嵌套 bind 要写决定路径',
bind: 'parent',
properties: {
e: {
title: '日期',
widget: 'input',
},
f: {
title: '日期',
widget: 'input',
},

}
}

}
}
}
};

const Demo = () => {
const form = useForm();

const onFinish = (formData) => {
console.log(formData, 'formData');
};

return (
<FormRender
form={form}
schema={schema}
onFinish={onFinish}
footer={true}
maxWidth={400}
onMount={() => {
form.setValues({
d: 1, e: 1, f: 1,
obj: {
c: 3,
a:1, b:1,
},


})
}
}
/>
);
};

export default Demo;

```



Expand Down
1 change: 1 addition & 0 deletions docs/form-render/advanced-layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,3 +367,4 @@ export default () => {
);
}
```
s
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"babel-plugin-no-debugger": "^0.0.1",
"babel-plugin-transform-remove-console": "^6.9.4",
"cross-env": "^7.0.3",
"dumi": "^2.0.2",
"dumi": "2.3.8",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.6",
"enzyme-to-json": "^3.6.2",
Expand Down
87 changes: 67 additions & 20 deletions packages/form-render/src/models/bindValues.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { get, set, unset } from 'lodash-es';
import { get, set, unset, assignIn } from 'lodash-es';
import {
_cloneDeep,
isArray,
Expand Down Expand Up @@ -29,24 +29,38 @@ const transformPath = (path: string) => {
return result;
};

const transformValueToBind = (data: any, path: any, bind: false | string | string[]) => {
// 将 formData 数据按照 bind 配置进行转换
const transformValuesToBind = (data: any, path: any, bind: false | string | string[], parentPath?: string) => {
// 配置 bind = false,在表单提交的时候可以将数据从 formData 中移除
if (bind === false) {
unset(data, path);
return;
}


// bind: string
if (typeof bind === 'string') {
let value = get(data, path);
const preValue = get(data, bind);
const preValue = get(data, bind === 'parent' ? parentPath : bind);
if (isObject(preValue)) {
value = { ...preValue, ...value };
}
set(data, bind, value);

// 更新数据
if (bind === 'root' || parentPath === '#') { // 数据绑定到根节点
assignIn(data, value)
} else if (bind === 'parent') { // 数据绑定到父节点
set(data, parentPath, value);
} else { // 数据绑定到指定节点
set(data, bind, value);
}

// 移除原数据
unset(data, path);
return;
}

// The array is converted to multiple fields.
// bind: string[], 例如:bind: ['obj.startDate', 'obj.endDate'],
// 结果 [startDate, endDate] => {obj: { startDate, endDate }}
if (isMultiBind(bind)) {
const value = get(data, path);
unset(data, path);
Expand All @@ -58,13 +72,42 @@ const transformValueToBind = (data: any, path: any, bind: false | string | strin
});
}
}
}
};

// 按照 Bind 配置还原 formData 数据
const transformBindToValue = (data: any, path: any, bind: false | string | string[], item?:any) => {
// bind: false 不用处理
if (bind === false) {
return;
}

const transformBindToValue = (data: any, path: any, bind: any) => {
// bind: string
if (typeof bind === 'string') {
let value = get(data, bind);
let value = get(data, bind) ;
const preValue = get(data, path);
if (isObject(preValue)) {

if (item?.children?.length > 0) {
value = { ...preValue, ...value };
let obj = null;
if (bind === 'root' || item.parent === '#') {
obj = data;
} else if (bind === 'parent') {
obj = get(data, item.parent);
}

item.children.forEach((item: any) => {
const list = item.split('.');
const key = list[list.length-1];
if (isObject(value[key])) {
value[key] = {
...value?.[key],
...obj?.[key]
}
} else if (!!obj) {
value[key] = obj[key];
}
})
} else if (isObject(preValue)) {
value = { ...preValue, ...value };
}
set(data, path, value);
Expand All @@ -90,16 +133,16 @@ const transformBindToValue = (data: any, path: any, bind: any) => {
}
}


// 转换表单数据
export const parseValuesToBind = (values: any, flatten: any) => {
// console.log(values, flatten, 'parseValuesToBind');
// No bind field exists, no processing
if (!JSON.stringify(flatten).includes('bind')) {
return values;
}

const data = _cloneDeep(values);

const dealFieldList = (obj: any, [path, ...rest]: any, bind: any) => {
const dealFieldList = (obj: any, [path, ...rest]: any, bind: any, ) => {
if (rest.length === 1) {
const list = get(obj, path, []);
list.forEach((item: any, index: number) => {
Expand All @@ -108,7 +151,7 @@ export const parseValuesToBind = (values: any, flatten: any) => {
list[index] = value;
return;
}
transformValueToBind(item, rest[0], bind);
transformValuesToBind(item, rest[0], bind);
});
}

Expand All @@ -122,22 +165,26 @@ export const parseValuesToBind = (values: any, flatten: any) => {

Object.keys(flatten).forEach(key => {
const bind = flatten[key]?.schema?.bind;
const parentPath = flatten[key]?.parent;
if (bind === undefined) {
return;
}
const path = transformPath(key);
isArray(path) ? dealFieldList(data, path, bind) : transformValueToBind(data, path, bind);
isArray(path) ? dealFieldList(data, path, bind) : transformValuesToBind(data, path, bind, parentPath);
});

return data;
};

// 还原表单数据
export const parseBindToValues = (values: any, flatten: any) => {
console.log(values, flatten, 'parseBindToValues');
// No bind field exists, no processing
if (!JSON.stringify(flatten).includes('bind')) {
return values;
}

const data = _cloneDeep(values);

const dealFieldList = (obj: any, [path, ...rest]: any, bind: any) => {
if (rest.length === 1) {
const list = get(obj, path, []);
Expand All @@ -157,15 +204,15 @@ export const parseBindToValues = (values: any, flatten: any) => {
dealFieldList(value, rest, bind);
}
};

Object.keys(flatten).forEach(key => {
const bind = flatten[key]?.schema?.bind;
const item = flatten[key];
const bind = item.schema?.bind;
if (bind === undefined) {
return;
}
const path = transformPath(key);

isArray(path) ? dealFieldList(data, path, bind) : transformBindToValue(data, path, bind);
isArray(path) ? dealFieldList(data, path, bind) : transformBindToValue(data, path, bind, item);
});

return data;
Expand Down
5 changes: 2 additions & 3 deletions packages/form-render/src/models/flattenSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ export function getSchemaFromFlatten(flatten: any, path = '#') {
export function flattenSchema(_schema = {}, name?: any, parent?: any, _result?: any) {
// 排序
// _schema = orderBy(_schema, item => item.order, ['asc']);

const result = _result || {};

const schema: any = _cloneDeep(_schema) || {};
Expand Down Expand Up @@ -79,9 +78,9 @@ export function flattenSchema(_schema = {}, name?: any, parent?: any, _result?:
}

if (schema.type) {
result[_name] = { parent, schema, children };

}

result[_name] = { parent, schema, children };
return result;
}

8 changes: 4 additions & 4 deletions packages/form-render/src/widgets/listDrawer/drawerForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@ import { Button, Drawer, Space, ConfigProvider } from 'antd';
import { translation } from '../utils';

const DrawerForm = (props: any) => {
const { children, onConfirm, onClose, DrawerProps } = props;
const { children, onConfirm, onClose, ...ret } = props;

const configCtx = useContext(ConfigProvider.ConfigContext);
const t = translation(configCtx);

let drawerProps: any = { ...DrawerProps, open: true };
let extraProps: any = { ...ret, open: true };
if ((window as any).antdVersion === 'v4') {
drawerProps = { ...DrawerProps, visible: true };
extraProps = { ...ret, visible: true };
}

return (
<Drawer
width={600}
title={t('operate')}
{...drawerProps}
{...extraProps}
onClose={onClose}
extra={
<Space>
Expand Down
5 changes: 3 additions & 2 deletions packages/form-render/src/widgets/listDrawer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ const TableList: React.FC<Props> = (props: any) => {
});
}

const drawerIndex = indexRef.current ?? (fields.length - 1);
return (
<div className='fr-list-drawer'>
<Table
Expand All @@ -257,15 +258,15 @@ const TableList: React.FC<Props> = (props: any) => {
)}
{visible && (
<FormDrawer
{...drawerProps}
schema={schema}
data={itemData}
widgets={widgets}
configContext={configContext}
onClose={handleRepeal}
onConfirm={hanldeConfirm}
DrawerProps={drawerProps}
>
{renderCore({ schema: schema.items, parentPath: [fields.length - 1], rootPath: [...rootPath, fields.length - 1] })}
{renderCore({ schema: schema.items, parentPath: [drawerIndex], rootPath: [...rootPath, drawerIndex] })}
</FormDrawer>
)}
</div>
Expand Down
Loading