feat(client): example of CollectionProvider + ResourceActionProvider
This commit is contained in:
parent
0440591868
commit
6036189063
@ -2,6 +2,7 @@ import { ArrayField } from '@formily/core';
|
||||
import { observer, RecursionField, Schema, useField, useFieldSchema } from '@formily/react';
|
||||
import { Table, TableColumnProps } from 'antd';
|
||||
import React from 'react';
|
||||
import { RecordProvider } from '../../../';
|
||||
import { useComponent } from '../../hooks';
|
||||
|
||||
const isColumnComponent = (schema: Schema) => {
|
||||
@ -24,7 +25,11 @@ const useTableColumns = () => {
|
||||
dataIndex: s.name,
|
||||
render: (v, record) => {
|
||||
const index = field.value?.indexOf(record);
|
||||
return <RecursionField schema={s} name={index} onlyRenderProperties />;
|
||||
return (
|
||||
<RecordProvider record={record}>
|
||||
<RecursionField schema={s} name={index} onlyRenderProperties />
|
||||
</RecordProvider>
|
||||
);
|
||||
},
|
||||
} as TableColumnProps<any>;
|
||||
});
|
||||
|
@ -13,7 +13,7 @@ export interface FormProps {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export type FormUseValues = (props?: FormProps, opts?: Opts) => Result<any, any>;
|
||||
export type FormUseValues = (opts?: Opts, props?: FormProps) => Result<any, any>;
|
||||
|
||||
const FormComponent: React.FC<FormProps> = (props) => {
|
||||
const { form, children, ...others } = props;
|
||||
@ -43,7 +43,7 @@ const useRequestProps = (props: any) => {
|
||||
};
|
||||
};
|
||||
|
||||
const useDef = (props: FormProps = {}, opts: any = {}) => {
|
||||
const useDef = (opts: any = {}, props: FormProps = {}) => {
|
||||
return useRequest(useRequestProps(props), opts);
|
||||
};
|
||||
|
||||
@ -51,13 +51,16 @@ export const Form: React.FC<FormProps> = observer((props) => {
|
||||
const { request, initialValue, useValues = useDef, ...others } = props;
|
||||
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);
|
||||
const { loading } = useValues(
|
||||
{
|
||||
uid: fieldSchema['x-uid'],
|
||||
async onSuccess(data) {
|
||||
await form.reset();
|
||||
form.setValues(data?.data);
|
||||
},
|
||||
},
|
||||
});
|
||||
props,
|
||||
);
|
||||
return (
|
||||
<Spin spinning={loading}>
|
||||
<FormComponent form={form} {...others} />
|
||||
|
@ -50,7 +50,7 @@ const useSubmit = () => {
|
||||
};
|
||||
};
|
||||
|
||||
const useValues: FormUseValues = (props, opts) => {
|
||||
const useValues: FormUseValues = (opts) => {
|
||||
return useRequest(() => {
|
||||
return Promise.resolve({ data: { field1: 'aabb' } });
|
||||
}, opts);
|
||||
|
@ -10,7 +10,7 @@ import { ArrayTable } from '../array-table';
|
||||
|
||||
type VoidTableProps = TableProps<any> & {
|
||||
request?: any;
|
||||
useDataSource?: (data?: any, options?: Options<any, any> & { uid?: string }) => Result<any, any>;
|
||||
useDataSource?: (options?: Options<any, any> & { uid?: string }, props?: any) => Result<any, any>;
|
||||
};
|
||||
|
||||
type VoidTableType = React.FC<VoidTableProps> & {
|
||||
@ -66,33 +66,36 @@ const useRequestProps = (props) => {
|
||||
};
|
||||
};
|
||||
|
||||
const useDefDataSource = (props, options) => {
|
||||
const useDef = (options, props) => {
|
||||
return useRequest(useRequestProps(props), options);
|
||||
};
|
||||
|
||||
export const VoidTable: VoidTableType = observer((props) => {
|
||||
const { useDataSource = useDefDataSource } = props;
|
||||
const { useDataSource = useDef } = props;
|
||||
const field = useField<Field>();
|
||||
const fieldSchema = useFieldSchema();
|
||||
const form = useMemo(() => createForm(), []);
|
||||
const f = useAttach(form.createArrayField({ name: fieldSchema.name }));
|
||||
const result = useDataSource(props, {
|
||||
uid: fieldSchema['x-uid'],
|
||||
onSuccess(data) {
|
||||
form.setValues({
|
||||
[fieldSchema.name]: data?.data,
|
||||
});
|
||||
if (field?.componentProps?.pagination === false) {
|
||||
return;
|
||||
}
|
||||
field.componentProps.pagination = field.componentProps.pagination || {};
|
||||
if (data?.meta?.count) {
|
||||
field.componentProps.pagination.total = data?.meta?.count;
|
||||
}
|
||||
field.componentProps.pagination.current = data?.meta?.page || 1;
|
||||
field.componentProps.pagination.pageSize = data?.meta?.pageSize || 10;
|
||||
const result = useDataSource(
|
||||
{
|
||||
uid: fieldSchema['x-uid'],
|
||||
onSuccess(data) {
|
||||
form.setValues({
|
||||
[fieldSchema.name]: data?.data,
|
||||
});
|
||||
if (field?.componentProps?.pagination === false) {
|
||||
return;
|
||||
}
|
||||
field.componentProps.pagination = field.componentProps.pagination || {};
|
||||
if (data?.meta?.count) {
|
||||
field.componentProps.pagination.total = data?.meta?.count;
|
||||
}
|
||||
field.componentProps.pagination.current = data?.meta?.page || 1;
|
||||
field.componentProps.pagination.pageSize = data?.meta?.pageSize || 10;
|
||||
},
|
||||
},
|
||||
});
|
||||
props,
|
||||
);
|
||||
return (
|
||||
<AsyncDataProvider value={result}>
|
||||
<FormContext.Provider value={form}>
|
||||
|
@ -1,19 +1,18 @@
|
||||
/**
|
||||
* title: 勾选
|
||||
*/
|
||||
import { ISchema, useField, useFieldSchema } from '@formily/react';
|
||||
import { uid } from '@formily/shared';
|
||||
import {
|
||||
AntdSchemaComponentProvider,
|
||||
APIClientProvider,
|
||||
CollectionField,
|
||||
CollectionManagerProvider,
|
||||
CollectionProvider,
|
||||
SchemaComponent,
|
||||
SchemaComponentProvider,
|
||||
useCollection
|
||||
useCollection,
|
||||
useDesignable,
|
||||
useRequest
|
||||
} from '@nocobase/client';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useDesignable } from '../../..';
|
||||
import React, { createContext, useContext, useEffect } from 'react';
|
||||
import { apiClient } from './apiClient';
|
||||
|
||||
const schema: ISchema = {
|
||||
@ -21,7 +20,22 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
block1: {
|
||||
type: 'void',
|
||||
'x-decorator': 'CollectionBlock',
|
||||
'x-decorator': 'CollectionProvider',
|
||||
'x-decorator-props': {
|
||||
name: 'posts',
|
||||
},
|
||||
'x-component': 'ResourceActionProvider',
|
||||
'x-component-props': {
|
||||
request: {
|
||||
resource: 'posts',
|
||||
action: 'list',
|
||||
params: {
|
||||
filter: {},
|
||||
sort: [],
|
||||
appends: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
properties: {
|
||||
table1: {
|
||||
type: 'void',
|
||||
@ -32,18 +46,7 @@ const schema: ISchema = {
|
||||
rowSelection: {
|
||||
type: 'checkbox',
|
||||
},
|
||||
pagination: {
|
||||
current: 2,
|
||||
pageSize: 2,
|
||||
},
|
||||
request: {
|
||||
resource: 'posts',
|
||||
action: 'list',
|
||||
params: {
|
||||
filter: {},
|
||||
// pageSize: 5,
|
||||
},
|
||||
},
|
||||
useDataSource: '{{ useDataSourceFromRAC }}',
|
||||
},
|
||||
properties: {
|
||||
column1: {
|
||||
@ -142,68 +145,85 @@ const TableColumnDecorator = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
const CollectionBlock = (props) => {
|
||||
return (
|
||||
<CollectionProvider
|
||||
collection={{
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'integer',
|
||||
name: 'id',
|
||||
interface: 'input',
|
||||
uiSchema: {
|
||||
title: 'ID1',
|
||||
type: 'number',
|
||||
'x-component': 'InputNumber',
|
||||
required: true,
|
||||
description: 'description1',
|
||||
} as ISchema,
|
||||
const collections = [
|
||||
{
|
||||
name: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'integer',
|
||||
name: 'id',
|
||||
interface: 'input',
|
||||
uiSchema: {
|
||||
title: 'ID1',
|
||||
type: 'number',
|
||||
'x-component': 'InputNumber',
|
||||
required: true,
|
||||
description: 'description1',
|
||||
} as ISchema,
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
interface: 'input',
|
||||
uiSchema: {
|
||||
title: 'Name1',
|
||||
type: 'string',
|
||||
'x-component': 'Input',
|
||||
required: true,
|
||||
description: 'description1',
|
||||
} as ISchema,
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'date',
|
||||
interface: 'datetime',
|
||||
uiSchema: {
|
||||
type: 'boolean',
|
||||
title: `Date1`,
|
||||
'x-read-pretty': true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'DatePicker',
|
||||
'x-component-props': {
|
||||
dateFormat: 'YYYY/MM/DD',
|
||||
// showTime: true,
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
interface: 'input',
|
||||
uiSchema: {
|
||||
title: 'Name1',
|
||||
type: 'string',
|
||||
'x-component': 'Input',
|
||||
required: true,
|
||||
description: 'description1',
|
||||
} as ISchema,
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
name: 'date',
|
||||
interface: 'datetime',
|
||||
uiSchema: {
|
||||
type: 'boolean',
|
||||
title: `Date1`,
|
||||
'x-read-pretty': true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'DatePicker',
|
||||
'x-component-props': {
|
||||
dateFormat: 'YYYY/MM/DD',
|
||||
// showTime: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
</CollectionProvider>
|
||||
);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const ResourceActionContext = createContext(null);
|
||||
|
||||
const ResourceActionProvider = (props) => {
|
||||
const { name } = useCollection();
|
||||
const { request } = props;
|
||||
const service = useRequest(request);
|
||||
return <ResourceActionContext.Provider value={{ service }}>{props.children}</ResourceActionContext.Provider>;
|
||||
};
|
||||
|
||||
const useDataSourceFromRAC = (options: any) => {
|
||||
const { service } = useContext(ResourceActionContext);
|
||||
useEffect(() => {
|
||||
if (!service.loading) {
|
||||
options?.onSuccess(service.data);
|
||||
}
|
||||
}, [service.loading]);
|
||||
return service;
|
||||
};
|
||||
|
||||
const componets = { CollectionProvider, TableColumnDecorator, ResourceActionProvider, CollectionField };
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<APIClientProvider apiClient={apiClient}>
|
||||
<SchemaComponentProvider components={{ TableColumnDecorator, CollectionBlock, CollectionField }}>
|
||||
<AntdSchemaComponentProvider>
|
||||
<SchemaComponent schema={schema} />
|
||||
</AntdSchemaComponentProvider>
|
||||
</SchemaComponentProvider>
|
||||
<CollectionManagerProvider collections={collections}>
|
||||
<SchemaComponentProvider components={componets}>
|
||||
<AntdSchemaComponentProvider>
|
||||
<SchemaComponent schema={schema} scope={{ useDataSourceFromRAC }} />
|
||||
</AntdSchemaComponentProvider>
|
||||
</SchemaComponentProvider>
|
||||
</CollectionManagerProvider>
|
||||
</APIClientProvider>
|
||||
);
|
||||
};
|
||||
|
@ -202,6 +202,50 @@ export default () => {
|
||||
|
||||
<code src="./demos/demo1.tsx">
|
||||
|
||||
CollectionProvider + CollectionField
|
||||
### CollectionProvider + ResourceActionProvider
|
||||
|
||||
<code src="./demos/demo2.tsx">
|
||||
|
||||
大纲
|
||||
|
||||
```tsx | pure
|
||||
<CollectionProvider> {/* 属于哪个 collection */}
|
||||
<ResourceActionProvider> {/* 发起请求,将请求结果存到上下文共享给子组件 */}
|
||||
<SettingsForm /> {/* 区块的配置表单 */}
|
||||
<ActionBar /> {/* 操作区 */}
|
||||
<Table/> {/* 具体的组件,如 Table、Form、Calendar 等 */}
|
||||
</ResourceActionProvider>
|
||||
</CollectionProvider>
|
||||
```
|
||||
|
||||
通过 CollectionProvider 和 ResourceActionProvider 来解决数据区块配置和数据请求,与具体组件无关,所有区块通用。在里面可以放任意东西。
|
||||
|
||||
嵌套使用的情况
|
||||
|
||||
```tsx | pure
|
||||
<CollectionProvider> {/* 属于哪个 collection */}
|
||||
<ResourceActionProvider> {/* 发起请求,将请求结果存到上下文共享给子组件 */}
|
||||
<SettingsForm /> {/* 区块的配置表单 */}
|
||||
<ActionBar /> {/* 操作区 */}
|
||||
<Table> {/* 具体的组件 */}
|
||||
<Table.Column>
|
||||
<SettingsForm /> {/* 表格列的配置表单 */}
|
||||
<RecordProvider> {/* 列表数据的行记录 */}
|
||||
<CollectionField>
|
||||
<CollectionFieldProvider> {/* 是哪个字段 */}
|
||||
<CollectionProvider> {/* 关联字段的关联表 collection */}
|
||||
<ResourceActionProvider> {/* 可能也会发起请求,如查看详情 */}
|
||||
<SettingsForm />
|
||||
<ActionBar />
|
||||
<Table />
|
||||
</ResourceActionProvider>
|
||||
</CollectionProvider>
|
||||
</CollectionFieldProvider>
|
||||
</CollectionField>
|
||||
</RecordProvider>
|
||||
</Table.Column>
|
||||
<Table.Column></Table.Column> {/* 会有很多列 */}
|
||||
</Table>
|
||||
</ResourceActionProvider>
|
||||
</CollectionProvider>
|
||||
```
|
||||
|
Loading…
Reference in New Issue
Block a user