fix: form submission broken when using nested form

This commit is contained in:
chenos 2021-01-16 17:25:19 +08:00
parent dba1f1fbc6
commit 5f5bb0a258
6 changed files with 143 additions and 81 deletions

View File

@ -17,7 +17,8 @@ export function Create(props) {
params['associatedName'] = associatedName; params['associatedName'] = associatedName;
params['associatedKey'] = associatedKey; params['associatedKey'] = associatedKey;
} else { } else {
params['resourceName'] = collection_name; params['resourceName'] = props.resourceName;
params['resourceTarget'] = collection_name;
params['resourceKey'] = item.itemId; params['resourceKey'] = item.itemId;
} }

View File

@ -6,6 +6,8 @@ import {
SchemaForm, SchemaForm,
SchemaMarkupField as Field, SchemaMarkupField as Field,
createFormActions, createFormActions,
FormSpy,
LifeCycleTypes,
createAsyncFormActions, createAsyncFormActions,
Submit, Submit,
Reset, Reset,
@ -32,6 +34,9 @@ export default forwardRef((props: any, ref) => {
const { data: schema = {}, loading } = useRequest(() => api.resource(target).getView({ const { data: schema = {}, loading } = useRequest(() => api.resource(target).getView({
resourceKey: 'form' resourceKey: 'form'
})); }));
const [state, setState] = useState<any>({});
const [form, setForm] = useState<any>({});
const [changed, setChanged] = useState(false);
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [data, setData] = useState({}); const [data, setData] = useState({});
const [title, setTitle] = useState('创建子字段'); const [title, setTitle] = useState('创建子字段');
@ -55,31 +60,18 @@ export default forwardRef((props: any, ref) => {
className={'noco-drawer'} className={'noco-drawer'}
width={'40%'} width={'40%'}
onClose={() => { onClose={() => {
actions.getFormState(state => { if (changed) {
const values = cleanDeep(state.values); Modal.confirm({
const others = Object.keys(data).length ? cleanDeep({...data}) : cleanDeep(state.initialValues); title: '表单内容发生变化,确定不保存吗?',
if (isEqual(values, others)) { onOk() {
setVisible(false); setChanged(false);
return; setVisible(false);
}
for (const key in values) {
if (Object.prototype.hasOwnProperty.call(values, key)) {
const value = values[key];
const other = others[key];
if (!isEqual(value, other)) {
// console.log(value, other, values, others, state.initialValues);
Modal.confirm({
title: '表单内容发生变化,确定不保存吗?',
onOk() {
setVisible(false);
}
});
return;
}
} }
} });
} else {
setChanged(false);
setVisible(false); setVisible(false);
}); }
}} }}
title={title} title={title}
footer={( footer={(
@ -89,11 +81,15 @@ export default forwardRef((props: any, ref) => {
}} }}
> >
<Space> <Space>
<Button onClick={() => setVisible(false)}></Button> <Button onClick={() => {
<Button type={'primary'} onClick={async () => {
const { values = {} } = await actions.submit();
setVisible(false); setVisible(false);
onFinish && onFinish(values, index); setChanged(false);
}}></Button>
<Button type={'primary'} onClick={async () => {
await form.submit();
// const { values = {} } = await actions.submit();
// setVisible(false);
// onFinish && onFinish(values, index);
}}></Button> }}></Button>
</Space> </Space>
</div> </div>
@ -103,13 +99,50 @@ export default forwardRef((props: any, ref) => {
colon={true} colon={true}
layout={'vertical'} layout={'vertical'}
initialValues={data} initialValues={data}
actions={actions} onChange={(values) => {
setChanged(true);
}}
onSubmit={async (values) => {
setVisible(false);
setChanged(false);
onFinish && onFinish(values, index);
}}
// actions={actions}
schema={{ schema={{
type: 'object', type: 'object',
properties: fields, properties: fields,
}} }}
expressionScope={scopes} expressionScope={scopes}
> >
<FormSpy
selector={[
LifeCycleTypes.ON_FORM_MOUNT,
LifeCycleTypes.ON_FORM_SUBMIT_START,
LifeCycleTypes.ON_FORM_SUBMIT_END
]}
reducer={(state, action) => {
switch (action.type) {
case LifeCycleTypes.ON_FORM_SUBMIT_START:
return {
...state,
submitting: true
}
case LifeCycleTypes.ON_FORM_SUBMIT_END:
return {
...state,
submitting: false
}
default:
return state
}
}}
>
{({ state, form }) => {
setState(state)
setForm(form);
return <div/>
}}
</FormSpy>
</SchemaForm> </SchemaForm>
</Drawer> </Drawer>
); );

View File

@ -101,7 +101,8 @@ export default function Table(props: SimpleTableProps) {
}, },
mutate: (values) => { mutate: (values) => {
onChange(values.list); onChange(values.list);
console.log(values); setDataSource(values.list);
console.log('mutate', values);
}, },
rowKey, rowKey,
onMoved: async ({resourceKey, target}) => { onMoved: async ({resourceKey, target}) => {

View File

@ -110,7 +110,7 @@ export function BooleanField(props: any) {
// console.log(props); // console.log(props);
}}/> }}/>
} }
console.log(props); // console.log(props);
return ( return (
<>{value ? <CheckOutlined style={{color: '#52c41a'}}/> : <CloseOutlined style={{color: '#f5222d'}}/>}</> <>{value ? <CheckOutlined style={{color: '#52c41a'}}/> : <CloseOutlined style={{color: '#f5222d'}}/>}</>
); );

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect, useImperativeHandle, forwardRef, useRef } from 'react'; import React, { useState, useEffect, useImperativeHandle, forwardRef, useRef, createRef } from 'react';
import { Button, Drawer, Modal } from 'antd'; import { Button, Drawer, Modal } from 'antd';
import { Tooltip, Input } from 'antd'; import { Tooltip, Input } from 'antd';
import { import {
@ -13,6 +13,8 @@ import {
FormValidator, FormValidator,
setValidationLanguage, setValidationLanguage,
FormEffectHooks, FormEffectHooks,
FormSpy,
LifeCycleTypes,
} from '@formily/antd'; } from '@formily/antd';
import { merge } from '@formily/shared'; import { merge } from '@formily/shared';
import { QuestionCircleOutlined } from '@ant-design/icons'; import { QuestionCircleOutlined } from '@ant-design/icons';
@ -25,8 +27,6 @@ import get from 'lodash/get';
import cleanDeep from 'clean-deep'; import cleanDeep from 'clean-deep';
import scopes from './scopes'; import scopes from './scopes';
const actions = createFormActions();
export const DrawerForm = forwardRef((props: any, ref) => { export const DrawerForm = forwardRef((props: any, ref) => {
console.log(props); console.log(props);
const { const {
@ -38,6 +38,9 @@ export const DrawerForm = forwardRef((props: any, ref) => {
associatedKey, associatedKey,
onFinish, onFinish,
} = props; } = props;
const [state, setState] = useState<any>({});
const [form, setForm] = useState<any>({});
const [changed, setChanged] = useState(false);
console.log(associatedKey); console.log(associatedKey);
const { title, actionDefaultParams = {}, fields: properties ={} } = props.schema||{}; const { title, actionDefaultParams = {}, fields: properties ={} } = props.schema||{};
const [resourceKey, setResourceKey] = useState(props.resourceKey); const [resourceKey, setResourceKey] = useState(props.resourceKey);
@ -57,8 +60,7 @@ export const DrawerForm = forwardRef((props: any, ref) => {
setVisible, setVisible,
getData: run, getData: run,
})); }));
console.log({onFinish});
return ( return (
<Drawer <Drawer
{...props} {...props}
@ -67,31 +69,19 @@ export const DrawerForm = forwardRef((props: any, ref) => {
width={'40%'} width={'40%'}
className={'noco-drawer'} className={'noco-drawer'}
onClose={() => { onClose={() => {
actions.getFormState(state => { if (changed) {
const values = cleanDeep(state.values); Modal.confirm({
const others = Object.keys(data).length ? cleanDeep({...data, associatedKey, resourceKey}) : cleanDeep(state.initialValues); title: '表单内容发生变化,确定不保存吗?',
if (isEqual(values, others)) { onOk() {
setVisible(false); setChanged(false);
return; setVisible(false);
}
for (const key in values) {
if (Object.prototype.hasOwnProperty.call(values, key)) {
const value = values[key];
const other = others[key];
if (!isEqual(value, other)) {
// console.log(value, other, values, others, state.initialValues);
Modal.confirm({
title: '表单内容发生变化,确定不保存吗?',
onOk() {
setVisible(false);
}
});
return;
}
} }
} });
} else {
setChanged(false);
setVisible(false); setVisible(false);
}); }
}} }}
title={title} title={title}
footer={( footer={(
@ -102,27 +92,11 @@ export const DrawerForm = forwardRef((props: any, ref) => {
> >
<Button onClick={() => { <Button onClick={() => {
setVisible(false); setVisible(false);
setChanged(false);
}}></Button> }}></Button>
<span style={{display: 'inline-block', width: 8}}> </span> <span style={{display: 'inline-block', width: 8}}> </span>
<Button type={'primary'} onClick={async () => { <Button loading={state.submitting} type={'primary'} onClick={async () => {
const { values = {} } = await actions.submit(); await form.submit();
console.log(values);
if (resourceKey) {
await api.resource(name).update({
resourceKey,
associatedKey,
values,
});
} else {
await api.resource(name).create({
associatedKey,
values,
});
}
setVisible(false);
// @ts-ignore
window.routesReload && window.routesReload();
onFinish && onFinish(values);
}}></Button> }}></Button>
</div> </div>
)} )}
@ -133,14 +107,67 @@ export const DrawerForm = forwardRef((props: any, ref) => {
layout={'vertical'} layout={'vertical'}
// 暂时先这么处理,如果有 associatedKey 注入表单里 // 暂时先这么处理,如果有 associatedKey 注入表单里
initialValues={{associatedKey, resourceKey, ...data}} initialValues={{associatedKey, resourceKey, ...data}}
actions={actions} // actions={actions}
schema={{ schema={{
type: 'object', type: 'object',
properties, properties,
}} }}
autoComplete={'off'} autoComplete={'off'}
expressionScope={scopes} expressionScope={scopes}
onChange={(values) => {
setChanged(true);
}}
onSubmit={async (values) => {
console.log(values);
console.log('submitsubmitsubmit', values);
if (resourceKey) {
await api.resource(name).update({
resourceKey,
associatedKey,
values,
});
} else {
await api.resource(name).create({
associatedKey,
values,
});
}
setVisible(false);
setChanged(false);
// @ts-ignore
window.routesReload && window.routesReload();
onFinish && onFinish(values);
}}
> >
<FormSpy
selector={[
LifeCycleTypes.ON_FORM_MOUNT,
LifeCycleTypes.ON_FORM_SUBMIT_START,
LifeCycleTypes.ON_FORM_SUBMIT_END
]}
reducer={(state, action) => {
switch (action.type) {
case LifeCycleTypes.ON_FORM_SUBMIT_START:
return {
...state,
submitting: true
}
case LifeCycleTypes.ON_FORM_SUBMIT_END:
return {
...state,
submitting: false
}
default:
return state
}
}}
>
{({ state, form }) => {
setState(state)
setForm(form);
return <div/>
}}
</FormSpy>
</SchemaForm> </SchemaForm>
)} )}
</Drawer> </Drawer>

View File

@ -16,7 +16,7 @@ import { QuestionCircleOutlined } from '@ant-design/icons';
import scopes from './scopes'; import scopes from './scopes';
export function FilterForm(props: any) { export function FilterForm(props: any) {
const actions = createAsyncFormActions(); // const actions = createAsyncFormActions();
const { setVisible, onTrigger } = props; const { setVisible, onTrigger } = props;
const { title, fields: properties ={} } = props.schema||{}; const { title, fields: properties ={} } = props.schema||{};
return ( return (
@ -24,7 +24,7 @@ export function FilterForm(props: any) {
colon={true} colon={true}
layout={'vertical'} layout={'vertical'}
initialValues={{}} initialValues={{}}
actions={actions} // actions={actions}
onReset={() => { onReset={() => {
setVisible && setVisible(false); setVisible && setVisible(false);
}} }}