fix(client): improve form schema component
This commit is contained in:
parent
01d172e5c4
commit
dd783f6554
@ -1,56 +1,22 @@
|
|||||||
import { FormLayout } from '@formily/antd';
|
import { FormLayout } from '@formily/antd';
|
||||||
import { createForm, FormPath } from '@formily/core';
|
import { createForm } from '@formily/core';
|
||||||
import {
|
import { FieldContext, FormContext, observer, useField, useFieldSchema } from '@formily/react';
|
||||||
FieldContext,
|
|
||||||
FormContext,
|
|
||||||
observer,
|
|
||||||
SchemaContext,
|
|
||||||
SchemaOptionsContext,
|
|
||||||
useField,
|
|
||||||
useFieldSchema
|
|
||||||
} from '@formily/react';
|
|
||||||
import { toJS } from '@formily/reactive';
|
|
||||||
import { Spin } from 'antd';
|
import { Spin } from 'antd';
|
||||||
import React, { useContext, useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { SchemaComponent, useAttach } from '../..';
|
import { useAttach } from '../..';
|
||||||
import { useRequest } from '../../../api-client';
|
import { useRequest } from '../../../api-client';
|
||||||
|
|
||||||
type ComposedForm = React.FC<any> & {
|
|
||||||
__NOCOBASE_FORM?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
const useFormDecorator = () => {
|
|
||||||
const field = useField();
|
|
||||||
const options = useContext(SchemaOptionsContext);
|
|
||||||
const decorator = field.decoratorType ? FormPath.getIn(options?.components, field.decoratorType) : null;
|
|
||||||
return decorator?.__NOCOBASE_FORM ? decorator : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const FormDecorator: React.FC<any> = (props) => {
|
|
||||||
const { form } = props;
|
|
||||||
const options = useContext(SchemaOptionsContext);
|
|
||||||
const field = useField();
|
|
||||||
const fieldSchema = useFieldSchema();
|
|
||||||
const f = useAttach(form.createVoidField({ ...field.props, basePath: '' }));
|
|
||||||
const finalComponent = FormPath.getIn(options?.components, field.componentType) ?? field.componentType;
|
|
||||||
return (
|
|
||||||
<FormContext.Provider value={form}>
|
|
||||||
<SchemaContext.Provider value={fieldSchema}>
|
|
||||||
<FieldContext.Provider value={f}>
|
|
||||||
{React.createElement(finalComponent, toJS(field.componentProps))}
|
|
||||||
</FieldContext.Provider>
|
|
||||||
</SchemaContext.Provider>
|
|
||||||
</FormContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const FormComponent: React.FC<any> = (props) => {
|
const FormComponent: React.FC<any> = (props) => {
|
||||||
const { form } = props;
|
const { form, children, ...others } = props;
|
||||||
const fieldSchema = useFieldSchema();
|
const field = useField();
|
||||||
|
// TODO: component 里 useField 会与当前 field 存在偏差
|
||||||
|
const f = useAttach(form.createVoidField({ ...field.props, basePath: '' }));
|
||||||
return (
|
return (
|
||||||
<FieldContext.Provider value={undefined}>
|
<FieldContext.Provider value={undefined}>
|
||||||
<FormContext.Provider value={form}>
|
<FormContext.Provider value={form}>
|
||||||
<SchemaComponent schema={fieldSchema} />
|
<FormLayout layout={'vertical'} {...others}>
|
||||||
|
<FieldContext.Provider value={f}>{children}</FieldContext.Provider>
|
||||||
|
</FormLayout>
|
||||||
</FormContext.Provider>
|
</FormContext.Provider>
|
||||||
</FieldContext.Provider>
|
</FieldContext.Provider>
|
||||||
);
|
);
|
||||||
@ -72,9 +38,8 @@ const useDefaultValues = (props: any = {}, opts: any = {}) => {
|
|||||||
return useRequest(useRequestProps(props), opts);
|
return useRequest(useRequestProps(props), opts);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Form: ComposedForm = observer((props) => {
|
export const Form: React.FC<any> = observer((props) => {
|
||||||
const { request, initialValue, useValues = useDefaultValues, ...others } = props;
|
const { request, initialValue, useValues = useDefaultValues, ...others } = props;
|
||||||
const decorator = useFormDecorator();
|
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const form = useMemo(() => createForm(), []);
|
const form = useMemo(() => createForm(), []);
|
||||||
const { loading } = useValues(props, {
|
const { loading } = useValues(props, {
|
||||||
@ -86,11 +51,7 @@ export const Form: ComposedForm = observer((props) => {
|
|||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<Spin spinning={loading}>
|
<Spin spinning={loading}>
|
||||||
<FormLayout layout={'vertical'} {...others}>
|
<FormComponent form={form} {...others} />
|
||||||
{decorator ? <FormDecorator form={form} /> : <FormComponent form={form} />}
|
|
||||||
</FormLayout>
|
|
||||||
</Spin>
|
</Spin>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Form.__NOCOBASE_FORM = true;
|
|
||||||
|
@ -11,7 +11,7 @@ export default observer(() => {
|
|||||||
form1: {
|
form1: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-decorator': 'Card',
|
'x-decorator': 'Card',
|
||||||
"x-decorator-props": {
|
'x-decorator-props': {
|
||||||
title: 'Form Title',
|
title: 'Form Title',
|
||||||
},
|
},
|
||||||
'x-component': 'Form',
|
'x-component': 'Form',
|
||||||
@ -20,6 +20,7 @@ export default observer(() => {
|
|||||||
'x-component': 'Input',
|
'x-component': 'Input',
|
||||||
'x-decorator': 'FormItem',
|
'x-decorator': 'FormItem',
|
||||||
title: 'T1',
|
title: 'T1',
|
||||||
|
required: true,
|
||||||
},
|
},
|
||||||
out: {
|
out: {
|
||||||
'x-component': 'Output',
|
'x-component': 'Output',
|
||||||
@ -46,6 +47,7 @@ export default observer(() => {
|
|||||||
const form = useForm();
|
const form = useForm();
|
||||||
return {
|
return {
|
||||||
async run() {
|
async run() {
|
||||||
|
await form.submit();
|
||||||
console.log(form.values);
|
console.log(form.values);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
import { FormItem, Input } from '@formily/antd';
|
||||||
|
import { ISchema, observer, useForm } from '@formily/react';
|
||||||
|
import { Action, Form, SchemaComponent, SchemaComponentProvider } from '@nocobase/client';
|
||||||
|
import { Card } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default observer(() => {
|
||||||
|
const schema: ISchema = {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
form1: {
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'Form',
|
||||||
|
'x-decorator-props': {
|
||||||
|
initialValue: {
|
||||||
|
field1: 'aaa',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'x-component': 'Card',
|
||||||
|
properties: {
|
||||||
|
field1: {
|
||||||
|
'x-component': 'Input',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
title: 'T1',
|
||||||
|
},
|
||||||
|
out: {
|
||||||
|
'x-component': 'Output',
|
||||||
|
},
|
||||||
|
action1: {
|
||||||
|
// type: 'void',
|
||||||
|
'x-component': 'Action',
|
||||||
|
title: 'Submit',
|
||||||
|
'x-component-props': {
|
||||||
|
useAction: '{{ useSubmit }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const Output = observer(() => {
|
||||||
|
const form = useForm();
|
||||||
|
return <pre>{JSON.stringify(form.values, null, 2)}</pre>;
|
||||||
|
});
|
||||||
|
|
||||||
|
const useSubmit = () => {
|
||||||
|
const form = useForm();
|
||||||
|
return {
|
||||||
|
async run() {
|
||||||
|
console.log(form.values);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SchemaComponentProvider scope={{ useSubmit }} components={{ Card, Output, Action, Form, Input, FormItem }}>
|
||||||
|
<SchemaComponent schema={schema} />
|
||||||
|
</SchemaComponentProvider>
|
||||||
|
);
|
||||||
|
});
|
@ -15,7 +15,11 @@ group:
|
|||||||
|
|
||||||
### Form Decorator
|
### Form Decorator
|
||||||
|
|
||||||
Form 也可以作 decorator 存在,和 Action.Drawer 结合就是 DrawerForm 了。
|
Form 也可以作 decorator 存在
|
||||||
|
|
||||||
|
<code src="./demos/demo6.tsx"/>
|
||||||
|
|
||||||
|
和 Action.Drawer 结合就是 DrawerForm 了
|
||||||
|
|
||||||
<code src="./demos/demo1.tsx"/>
|
<code src="./demos/demo1.tsx"/>
|
||||||
|
|
||||||
|
@ -146,8 +146,8 @@ export default function App() {
|
|||||||
schema={{
|
schema={{
|
||||||
type: 'void',
|
type: 'void',
|
||||||
name: 'page',
|
name: 'page',
|
||||||
'x-decorator': 'Page',
|
'x-decorator': 'Form',
|
||||||
'x-component': 'Form',
|
'x-component': 'Page',
|
||||||
properties: {
|
properties: {
|
||||||
title: {
|
title: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
|
Loading…
Reference in New Issue
Block a user