fix: field component (#4102)

* fix: field component

* chore: fix e2e

* fix: optimize CollectionField

* fix: add test case

---------

Co-authored-by: Zeke Zhang <958414905@qq.com>
This commit is contained in:
chenos 2024-04-19 22:52:55 +08:00 committed by GitHub
parent 31c5ff6624
commit 7b9e5c2cde
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 33 additions and 14 deletions

View File

@ -1,18 +1,19 @@
import React from 'react';
import { render, screen } from '@nocobase/test/client';
import { import {
Application,
CollectionField, CollectionField,
CollectionProvider, CollectionProvider,
Application, DataSourceApplicationProvider,
FormItem, FormItem,
Input, Input,
SchemaComponent, SchemaComponent,
SchemaComponentProvider, SchemaComponentProvider,
DataSourceApplicationProvider, useCollectionField,
} from '@nocobase/client'; } from '@nocobase/client';
import { render, screen } from '@nocobase/test/client';
import React from 'react';
import collections from '../collections.json'; import collections from '../collections.json';
function renderApp(fieldName: string) { function renderApp(fieldName: string, components = {}) {
const noUiSchema = { const noUiSchema = {
key: 'no-ui-schema', key: 'no-ui-schema',
name: 'no-ui-schema', name: 'no-ui-schema',
@ -49,7 +50,10 @@ function renderApp(fieldName: string) {
<SchemaComponentProvider designable={true}> <SchemaComponentProvider designable={true}>
<DataSourceApplicationProvider dataSourceManager={app.dataSourceManager}> <DataSourceApplicationProvider dataSourceManager={app.dataSourceManager}>
<CollectionProvider name="users"> <CollectionProvider name="users">
<SchemaComponent schema={schema} components={{ CollectionField: CollectionField, FormItem, Input }} /> <SchemaComponent
schema={schema}
components={{ CollectionField: CollectionField, FormItem, Input, ...components }}
/>
</CollectionProvider> </CollectionProvider>
</DataSourceApplicationProvider> </DataSourceApplicationProvider>
</SchemaComponentProvider> </SchemaComponentProvider>
@ -64,6 +68,15 @@ describe('CollectionField', () => {
expect(screen.getByRole('textbox')).toHaveClass('ant-input'); expect(screen.getByRole('textbox')).toHaveClass('ant-input');
}); });
it('context', () => {
const Input = () => {
const field = useCollectionField();
return <div className={'input-test-1'}>{field?.name}</div>;
};
renderApp('nickname', { Input });
expect(document.querySelector('.input-test-1')).toHaveTextContent('nickname');
});
it('no schema', () => { it('no schema', () => {
renderApp('no-ui-schema'); renderApp('no-ui-schema');
expect(document.querySelector('.ant-formily-item-control-content-component')).toHaveTextContent(''); expect(document.querySelector('.ant-formily-item-control-content-component')).toHaveTextContent('');

View File

@ -6,7 +6,7 @@ import React, { useCallback, useEffect, useMemo } from 'react';
import { useFormBlockContext } from '../../block-provider/FormBlockProvider'; import { useFormBlockContext } from '../../block-provider/FormBlockProvider';
import { useCompile, useComponent } from '../../schema-component'; import { useCompile, useComponent } from '../../schema-component';
import { useIsAllowToSetDefaultValue } from '../../schema-settings/hooks/useIsAllowToSetDefaultValue'; import { useIsAllowToSetDefaultValue } from '../../schema-settings/hooks/useIsAllowToSetDefaultValue';
import { CollectionFieldProvider, useCollectionField } from './CollectionFieldProvider'; import { CollectionFieldContext, CollectionFieldProvider, useCollectionField } from './CollectionFieldProvider';
type Props = { type Props = {
component: any; component: any;
@ -22,7 +22,8 @@ export const CollectionFieldInternalField: React.FC = (props: Props) => {
const compile = useCompile(); const compile = useCompile();
const field = useField<Field>(); const field = useField<Field>();
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const { uiSchema: uiSchemaOrigin, defaultValue } = useCollectionField(); const collectionField = useCollectionField();
const { uiSchema: uiSchemaOrigin, defaultValue } = collectionField;
const { isAllowToSetDefaultValue } = useIsAllowToSetDefaultValue(); const { isAllowToSetDefaultValue } = useIsAllowToSetDefaultValue();
const uiSchema = useMemo(() => compile(uiSchemaOrigin), [JSON.stringify(uiSchemaOrigin)]); const uiSchema = useMemo(() => compile(uiSchemaOrigin), [JSON.stringify(uiSchemaOrigin)]);
const Component = useComponent(component || uiSchema?.['x-component'] || 'Input'); const Component = useComponent(component || uiSchema?.['x-component'] || 'Input');
@ -73,12 +74,17 @@ export const CollectionFieldInternalField: React.FC = (props: Props) => {
field.dataSource = uiSchema.enum; field.dataSource = uiSchema.enum;
const originalProps = compile(uiSchema['x-component-props']) || {}; const originalProps = compile(uiSchema['x-component-props']) || {};
const componentProps = merge(originalProps, field.componentProps || {}); const componentProps = merge(originalProps, field.componentProps || {});
field.component = [Component, componentProps]; field.component = [
(props) => (
<CollectionFieldContext.Provider value={collectionField}>
<Component {...props} />
</CollectionFieldContext.Provider>
),
componentProps,
];
}, [uiSchema]); }, [uiSchema]);
if (!uiSchema) {
return null; return null;
}
return <Component {...props} />;
}; };
export const CollectionField = connect((props) => { export const CollectionField = connect((props) => {

View File

@ -2,11 +2,11 @@ import { observer } from '@formily/react';
import React from 'react'; import React from 'react';
import { AssociationFieldProvider } from './AssociationFieldProvider'; import { AssociationFieldProvider } from './AssociationFieldProvider';
import { FileManageReadPretty } from './FileManager'; import { FileManageReadPretty } from './FileManager';
import { useAssociationFieldContext } from './hooks';
import { InternalNester } from './InternalNester'; import { InternalNester } from './InternalNester';
import { InternalSubTable } from './InternalSubTable'; import { InternalSubTable } from './InternalSubTable';
import { ReadPrettyInternalTag } from './InternalTag'; import { ReadPrettyInternalTag } from './InternalTag';
import { ReadPrettyInternalViewer } from './InternalViewer'; import { ReadPrettyInternalViewer } from './InternalViewer';
import { useAssociationFieldContext } from './hooks';
const ReadPrettyAssociationField = observer( const ReadPrettyAssociationField = observer(
(props: any) => { (props: any) => {