mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 06:06:25 +00:00
fix: collection field support x-use-component-props (#4264)
* fix: collection field support x-use-component-props * fix: bug * fix: bug
This commit is contained in:
parent
1e5e015b73
commit
2014729e01
@ -12,36 +12,9 @@ import React, { ComponentType, useMemo } from 'react';
|
||||
import { useDesignable } from '../../schema-component';
|
||||
import _ from 'lodash';
|
||||
|
||||
const useDefaultSchemaProps = () => undefined;
|
||||
const useDefaultDynamicComponentProps = () => undefined;
|
||||
|
||||
interface WithSchemaHookOptions {
|
||||
displayName?: string;
|
||||
}
|
||||
|
||||
export function withDynamicSchemaProps<T = any>(
|
||||
Component: React.ComponentType<T>,
|
||||
options: WithSchemaHookOptions = {},
|
||||
) {
|
||||
const displayName = options.displayName || Component.displayName || Component.name;
|
||||
const ComponentWithProps: ComponentType<T> = (props) => {
|
||||
const { dn, findComponent } = useDesignable();
|
||||
const scope = useExpressionScope();
|
||||
const useComponentPropsStr = useMemo(() => {
|
||||
const xComponent = dn.getSchemaAttribute('x-component');
|
||||
const xDecorator = dn.getSchemaAttribute('x-decorator');
|
||||
const xUseComponentProps = dn.getSchemaAttribute('x-use-component-props');
|
||||
const xUseDecoratorProps = dn.getSchemaAttribute('x-use-decorator-props');
|
||||
|
||||
if (xComponent && xUseComponentProps && findComponent(xComponent) === ComponentWithProps) {
|
||||
return xUseComponentProps;
|
||||
}
|
||||
|
||||
if (xDecorator && xUseDecoratorProps && findComponent(xDecorator) === ComponentWithProps) {
|
||||
return xUseDecoratorProps;
|
||||
}
|
||||
}, [dn]);
|
||||
const useSchemaProps = useMemo(() => {
|
||||
const getHook = (str: string, scope: Record<string, any>, allText: string) => {
|
||||
const getHook = (str: string, scope: Record<string, any>, allText: string) => {
|
||||
let res = undefined;
|
||||
if (_.isFunction(str)) {
|
||||
res = str;
|
||||
@ -51,11 +24,15 @@ export function withDynamicSchemaProps<T = any>(
|
||||
console.error(`${allText} is not registered`);
|
||||
}
|
||||
}
|
||||
return res || useDefaultSchemaProps;
|
||||
};
|
||||
return res || useDefaultDynamicComponentProps;
|
||||
};
|
||||
|
||||
export function useDynamicComponentProps(useComponentPropsStr?: string, props?: any) {
|
||||
const scope = useExpressionScope();
|
||||
|
||||
const useDynamicProps = useMemo(() => {
|
||||
if (!useComponentPropsStr) {
|
||||
return useDefaultSchemaProps;
|
||||
return useDefaultDynamicComponentProps;
|
||||
}
|
||||
|
||||
if (_.isFunction(useComponentPropsStr)) {
|
||||
@ -70,8 +47,39 @@ export function withDynamicSchemaProps<T = any>(
|
||||
}
|
||||
|
||||
return result;
|
||||
}, [scope, useComponentPropsStr]);
|
||||
const schemaProps = useSchemaProps(props);
|
||||
}, [useComponentPropsStr]);
|
||||
|
||||
const res = useDynamicProps(props);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
interface WithSchemaHookOptions {
|
||||
displayName?: string;
|
||||
}
|
||||
|
||||
export function withDynamicSchemaProps<T = any>(
|
||||
Component: React.ComponentType<T>,
|
||||
options: WithSchemaHookOptions = {},
|
||||
) {
|
||||
const displayName = options.displayName || Component.displayName || Component.name;
|
||||
const ComponentWithProps: ComponentType<T> = (props) => {
|
||||
const { dn, findComponent } = useDesignable();
|
||||
const useComponentPropsStr = useMemo(() => {
|
||||
const xComponent = dn.getSchemaAttribute('x-component');
|
||||
const xDecorator = dn.getSchemaAttribute('x-decorator');
|
||||
const xUseComponentProps = dn.getSchemaAttribute('x-use-component-props');
|
||||
const xUseDecoratorProps = dn.getSchemaAttribute('x-use-decorator-props');
|
||||
|
||||
if (xComponent && xUseComponentProps && findComponent(xComponent) === ComponentWithProps) {
|
||||
return xUseComponentProps;
|
||||
}
|
||||
|
||||
if (xDecorator && xUseDecoratorProps && findComponent(xDecorator) === ComponentWithProps) {
|
||||
return xUseDecoratorProps;
|
||||
}
|
||||
}, [dn]);
|
||||
const schemaProps = useDynamicComponentProps(useComponentPropsStr, props);
|
||||
|
||||
const memoProps = useMemo(() => {
|
||||
return { ...props, ...schemaProps };
|
||||
|
@ -34,8 +34,34 @@ function renderApp(fieldName: string, components = {}) {
|
||||
reverseKey: null,
|
||||
};
|
||||
|
||||
const useCustomDynamicProps = () => {
|
||||
return {
|
||||
addonBefore: 'addonBefore',
|
||||
};
|
||||
};
|
||||
|
||||
const dynamicPropsSchema = {
|
||||
key: 'dynamic-props',
|
||||
name: 'dynamic-props',
|
||||
type: 'string',
|
||||
interface: 'select',
|
||||
description: null,
|
||||
collectionName: 't_vwpds9fs4xs',
|
||||
parentKey: null,
|
||||
reverseKey: null,
|
||||
uiSchema: {
|
||||
type: 'string',
|
||||
'x-component': 'Input',
|
||||
'x-component-props': {
|
||||
placeholder: 'placeholder',
|
||||
},
|
||||
'x-use-component-props': 'useCustomDynamicProps',
|
||||
},
|
||||
};
|
||||
|
||||
const usersCollection: any = collections[0];
|
||||
usersCollection.fields.push(noUiSchema);
|
||||
usersCollection.fields.push(dynamicPropsSchema);
|
||||
|
||||
const app = new Application({
|
||||
dataSourceManager: {
|
||||
@ -61,6 +87,7 @@ function renderApp(fieldName: string, components = {}) {
|
||||
<CollectionProvider name="users">
|
||||
<SchemaComponent
|
||||
schema={schema}
|
||||
scope={{ useCustomDynamicProps }}
|
||||
components={{ CollectionField: CollectionField, FormItem, Input, ...components }}
|
||||
/>
|
||||
</CollectionProvider>
|
||||
@ -86,6 +113,12 @@ describe('CollectionField', () => {
|
||||
expect(document.querySelector('.input-test-1')).toHaveTextContent('nickname');
|
||||
});
|
||||
|
||||
it('useComponentProps', () => {
|
||||
renderApp('dynamic-props');
|
||||
expect(document.querySelector('.ant-input')).toHaveAttribute('placeholder', 'placeholder');
|
||||
expect(screen.queryByText('addonBefore')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('no schema', () => {
|
||||
renderApp('no-ui-schema');
|
||||
expect(document.querySelector('.ant-formily-item-control-content-component')).toHaveTextContent('');
|
||||
|
@ -16,6 +16,7 @@ import { useFormBlockContext } from '../../block-provider/FormBlockProvider';
|
||||
import { useCompile, useComponent } from '../../schema-component';
|
||||
import { useIsAllowToSetDefaultValue } from '../../schema-settings/hooks/useIsAllowToSetDefaultValue';
|
||||
import { CollectionFieldProvider, useCollectionField } from './CollectionFieldProvider';
|
||||
import { useDynamicComponentProps } from '../../application/hoc';
|
||||
|
||||
type Props = {
|
||||
component: any;
|
||||
@ -49,6 +50,8 @@ export const CollectionFieldInternalField: React.FC = (props: Props) => {
|
||||
}, [fieldSchema, uiSchema]);
|
||||
const ctx = useFormBlockContext();
|
||||
|
||||
const dynamicProps = useDynamicComponentProps(uiSchema?.['x-use-component-props'], props);
|
||||
|
||||
useEffect(() => {
|
||||
if (ctx?.field) {
|
||||
ctx.field.added = ctx.field.added || new Set();
|
||||
@ -82,12 +85,12 @@ export const CollectionFieldInternalField: React.FC = (props: Props) => {
|
||||
// @ts-ignore
|
||||
field.dataSource = uiSchema.enum;
|
||||
const originalProps = compile(uiSchema['x-component-props']) || {};
|
||||
field.componentProps = merge(originalProps, field.componentProps || {});
|
||||
field.componentProps = merge(originalProps, field.componentProps || {}, dynamicProps || {});
|
||||
}, [uiSchema]);
|
||||
|
||||
if (!uiSchema) return null;
|
||||
|
||||
return <Component {...props} />;
|
||||
return <Component {...props} {...dynamicProps} />;
|
||||
};
|
||||
|
||||
export const CollectionField = connect((props) => {
|
||||
|
Loading…
Reference in New Issue
Block a user