diff --git a/packages/client/src/schema-component/antd/form/Form.tsx b/packages/client/src/schema-component/antd/form/Form.tsx index 210130e69..8b7ba1987 100644 --- a/packages/client/src/schema-component/antd/form/Form.tsx +++ b/packages/client/src/schema-component/antd/form/Form.tsx @@ -1,17 +1,18 @@ -import React, { useContext, useMemo } from 'react'; -import { toJS } from '@formily/reactive'; import { createForm, FormPath } from '@formily/core'; import { FieldContext, FormContext, - FormProvider, observer, SchemaContext, SchemaOptionsContext, useField, - useFieldSchema, + useFieldSchema } from '@formily/react'; +import { toJS } from '@formily/reactive'; +import { Spin } from 'antd'; +import React, { useContext, useMemo } from 'react'; import { SchemaComponent, useAttach } from '../..'; +import { useRequest } from '../../../api-client'; type ComposedForm = React.FC & { __NOCOBASE_FORM?: boolean; @@ -42,17 +43,47 @@ const FormDecorator: React.FC = (props) => { ); }; -export const Form: ComposedForm = observer((props) => { - const form = useMemo(() => createForm(), []); +const FormComponent: React.FC = (props) => { + const { form } = props; const fieldSchema = useFieldSchema(); - const decorator = useFormDecorator(); - return decorator ? ( - - ) : ( - - - + return ( + + + + + ); +}; + +const useRequestProps = (props: any) => { + const { request, initialValue } = props; + if (request) { + return request; + } + return () => { + return Promise.resolve({ + data: initialValue, + }); + }; +}; + +const useDefaultValues = (props: any = {}, opts: any = {}) => { + return useRequest(useRequestProps(props), opts); +}; + +export const Form: ComposedForm = observer((props) => { + const { useValues = useDefaultValues } = props; + const decorator = useFormDecorator(); + const fieldSchema = useFieldSchema(); + const form = useMemo(() => createForm(), []); + const { loading } = useValues(props, { + uid: fieldSchema['x-uid'], + async onSuccess(data) { + await form.reset(); + form.setValues(data?.data); + }, + }); + return {decorator ? : }; }); Form.__NOCOBASE_FORM = true; diff --git a/packages/client/src/schema-component/antd/form/demos/apiClient.ts b/packages/client/src/schema-component/antd/form/demos/apiClient.ts new file mode 100644 index 000000000..28c15e936 --- /dev/null +++ b/packages/client/src/schema-component/antd/form/demos/apiClient.ts @@ -0,0 +1,21 @@ +import { uid } from '@formily/shared'; +import { APIClient } from '@nocobase/client'; +import MockAdapter from 'axios-mock-adapter'; + +export const apiClient = new APIClient(); + +const mock = new MockAdapter(apiClient.axios); + +const sleep = (value: number) => new Promise((resolve) => setTimeout(resolve, value)); + +mock.onGet('/posts:get').reply(async (config) => { + await sleep(1000); + return [ + 200, + { + data: { + field1: uid(), + }, + }, + ]; +}); diff --git a/packages/client/src/schema-component/antd/form/demos/demo1.tsx b/packages/client/src/schema-component/antd/form/demos/demo1.tsx index 95d6ec921..9eab608bc 100644 --- a/packages/client/src/schema-component/antd/form/demos/demo1.tsx +++ b/packages/client/src/schema-component/antd/form/demos/demo1.tsx @@ -1,7 +1,7 @@ -import React from 'react'; -import { observer, ISchema } from '@formily/react'; -import { SchemaComponent, SchemaComponentProvider, Form, Action, useCloseAction } from '@nocobase/client'; import { FormItem, Input } from '@formily/antd'; +import { ISchema, observer, useForm } from '@formily/react'; +import { Action, Form, SchemaComponent, SchemaComponentProvider, useCloseAction } from '@nocobase/client'; +import React from 'react'; export default observer(() => { const schema: ISchema = { @@ -26,6 +26,9 @@ export default observer(() => { 'x-decorator': 'FormItem', title: 'T1', }, + out: { + 'x-component': 'Output', + }, f1: { type: 'void', 'x-component': 'Action.Drawer.Footer', @@ -45,8 +48,14 @@ export default observer(() => { }, }, }; + + const Output = observer(() => { + const form = useForm(); + return
{JSON.stringify(form.values, null, 2)}
; + }); + return ( - + ); diff --git a/packages/client/src/schema-component/antd/form/demos/demo2.tsx b/packages/client/src/schema-component/antd/form/demos/demo2.tsx index 8baa9e805..8d0e91796 100644 --- a/packages/client/src/schema-component/antd/form/demos/demo2.tsx +++ b/packages/client/src/schema-component/antd/form/demos/demo2.tsx @@ -1,7 +1,8 @@ -import React from 'react'; -import { observer, ISchema, useForm } from '@formily/react'; -import { SchemaComponent, SchemaComponentProvider, Form, Action } from '@nocobase/client'; 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 = { @@ -9,6 +10,10 @@ export default observer(() => { properties: { form1: { type: 'void', + 'x-decorator': 'Card', + "x-decorator-props": { + title: 'Form Title', + }, 'x-component': 'Form', properties: { field1: { @@ -16,6 +21,9 @@ export default observer(() => { 'x-decorator': 'FormItem', title: 'T1', }, + out: { + 'x-component': 'Output', + }, action1: { // type: 'void', 'x-component': 'Action', @@ -29,6 +37,11 @@ export default observer(() => { }, }; + const Output = observer(() => { + const form = useForm(); + return
{JSON.stringify(form.values, null, 2)}
; + }); + const useSubmit = () => { const form = useForm(); return { @@ -39,7 +52,7 @@ export default observer(() => { }; return ( - + ); diff --git a/packages/client/src/schema-component/antd/form/demos/demo3.tsx b/packages/client/src/schema-component/antd/form/demos/demo3.tsx new file mode 100644 index 000000000..87cf4589f --- /dev/null +++ b/packages/client/src/schema-component/antd/form/demos/demo3.tsx @@ -0,0 +1,60 @@ +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-component': 'Form', + 'x-component-props': { + initialValue: { + field1: 'aaa', + }, + }, + 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
{JSON.stringify(form.values, null, 2)}
; + }); + + const useSubmit = () => { + const form = useForm(); + return { + async run() { + console.log(form.values); + }, + }; + }; + + return ( + + + + ); +}); diff --git a/packages/client/src/schema-component/antd/form/demos/demo4.tsx b/packages/client/src/schema-component/antd/form/demos/demo4.tsx new file mode 100644 index 000000000..904fbac89 --- /dev/null +++ b/packages/client/src/schema-component/antd/form/demos/demo4.tsx @@ -0,0 +1,67 @@ +import { FormItem, Input } from '@formily/antd'; +import { ISchema, observer, useForm } from '@formily/react'; +import { Action, Form, SchemaComponent, SchemaComponentProvider, useCloseAction } from '@nocobase/client'; +import React from 'react'; + +export default observer(() => { + const schema: ISchema = { + type: 'object', + properties: { + a1: { + type: 'void', + 'x-component': 'Action', + 'x-component-props': { + type: 'primary', + }, + title: 'Open', + properties: { + d1: { + type: 'void', + 'x-component': 'Action.Drawer', + 'x-decorator': 'Form', + 'x-decorator-props': { + initialValue: { + field1: 'aaa', + }, + }, + title: 'Drawer Title', + properties: { + field1: { + title: 'T1', + 'x-component': 'Input', + 'x-decorator': 'FormItem', + }, + out: { + 'x-component': 'Output', + }, + f1: { + type: 'void', + 'x-component': 'Action.Drawer.Footer', + properties: { + a1: { + 'x-component': 'Action', + title: 'Close', + 'x-component-props': { + useAction: '{{ useCloseAction }}', + }, + }, + }, + }, + }, + }, + }, + }, + }, + }; + + const Output = observer(() => { + const form = useForm(); + return
{JSON.stringify(form.values, null, 2)}
; + }); + + return ( + + + + ); +}); diff --git a/packages/client/src/schema-component/antd/form/demos/demo5.tsx b/packages/client/src/schema-component/antd/form/demos/demo5.tsx new file mode 100644 index 000000000..e41c45d2f --- /dev/null +++ b/packages/client/src/schema-component/antd/form/demos/demo5.tsx @@ -0,0 +1,106 @@ +import { FormItem, Input } from '@formily/antd'; +import { ISchema, observer, useForm } from '@formily/react'; +import { + Action, + APIClientProvider, + Form, + SchemaComponent, + SchemaComponentProvider, + useAPIClient +} from '@nocobase/client'; +import { Card, Space } from 'antd'; +import React from 'react'; +import { apiClient } from './apiClient'; + +export default observer(() => { + const schema: ISchema = { + type: 'object', + properties: { + form1: { + type: 'void', + 'x-uid': 'form1', + 'x-component': 'Form', + 'x-component-props': { + request: { + resource: 'posts', + action: 'get', + }, + }, + properties: { + field1: { + title: 'T1', + 'x-component': 'Input', + 'x-decorator': 'FormItem', + }, + field2: { + title: 'T2', + 'x-component': 'Input', + 'x-decorator': 'FormItem', + required: true, + default: 'default value', + }, + out: { + 'x-component': 'Output', + }, + Space: { + type: 'void', + 'x-component': 'Space', + properties: { + action2: { + // type: 'void', + 'x-component': 'Action', + title: 'Submit', + 'x-component-props': { + useAction: '{{ useSubmit }}', + }, + }, + action1: { + // type: 'void', + title: 'Refresh', + 'x-component': 'Action', + 'x-component-props': { + useAction: '{{ useRefresh }}', + }, + }, + }, + }, + }, + }, + }, + }; + + const Output = observer(() => { + const form = useForm(); + return
{JSON.stringify(form.values, null, 2)}
; + }); + + const useSubmit = () => { + const form = useForm(); + return { + async run() { + await form.submit(); + console.log(form.values); + }, + }; + }; + + const useRefresh = () => { + const apiClient = useAPIClient(); + return { + async run() { + apiClient.service('form1')?.refresh(); + }, + }; + }; + + return ( + + + + + + ); +}); diff --git a/packages/client/src/schema-component/antd/form/index.md b/packages/client/src/schema-component/antd/form/index.md index 1dac6222d..9f2eb65bc 100644 --- a/packages/client/src/schema-component/antd/form/index.md +++ b/packages/client/src/schema-component/antd/form/index.md @@ -7,8 +7,26 @@ group: # Form +## Examples + +### 基础用法 + +### Form Decorator + Form 也可以作 decorator 存在,和 Action.Drawer 结合就是 DrawerForm 了。 + +### initialValue 初始化 + + + +### decorator 的 initialValue + + + +### 远程初始化数据 + +