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 {
Application,
CollectionField,
CollectionProvider,
Application,
DataSourceApplicationProvider,
FormItem,
Input,
SchemaComponent,
SchemaComponentProvider,
DataSourceApplicationProvider,
useCollectionField,
} from '@nocobase/client';
import { render, screen } from '@nocobase/test/client';
import React from 'react';
import collections from '../collections.json';
function renderApp(fieldName: string) {
function renderApp(fieldName: string, components = {}) {
const noUiSchema = {
key: 'no-ui-schema',
name: 'no-ui-schema',
@ -49,7 +50,10 @@ function renderApp(fieldName: string) {
<SchemaComponentProvider designable={true}>
<DataSourceApplicationProvider dataSourceManager={app.dataSourceManager}>
<CollectionProvider name="users">
<SchemaComponent schema={schema} components={{ CollectionField: CollectionField, FormItem, Input }} />
<SchemaComponent
schema={schema}
components={{ CollectionField: CollectionField, FormItem, Input, ...components }}
/>
</CollectionProvider>
</DataSourceApplicationProvider>
</SchemaComponentProvider>
@ -64,6 +68,15 @@ describe('CollectionField', () => {
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', () => {
renderApp('no-ui-schema');
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 { useCompile, useComponent } from '../../schema-component';
import { useIsAllowToSetDefaultValue } from '../../schema-settings/hooks/useIsAllowToSetDefaultValue';
import { CollectionFieldProvider, useCollectionField } from './CollectionFieldProvider';
import { CollectionFieldContext, CollectionFieldProvider, useCollectionField } from './CollectionFieldProvider';
type Props = {
component: any;
@ -22,7 +22,8 @@ export const CollectionFieldInternalField: React.FC = (props: Props) => {
const compile = useCompile();
const field = useField<Field>();
const fieldSchema = useFieldSchema();
const { uiSchema: uiSchemaOrigin, defaultValue } = useCollectionField();
const collectionField = useCollectionField();
const { uiSchema: uiSchemaOrigin, defaultValue } = collectionField;
const { isAllowToSetDefaultValue } = useIsAllowToSetDefaultValue();
const uiSchema = useMemo(() => compile(uiSchemaOrigin), [JSON.stringify(uiSchemaOrigin)]);
const Component = useComponent(component || uiSchema?.['x-component'] || 'Input');
@ -73,12 +74,17 @@ export const CollectionFieldInternalField: React.FC = (props: Props) => {
field.dataSource = uiSchema.enum;
const originalProps = compile(uiSchema['x-component-props']) || {};
const componentProps = merge(originalProps, field.componentProps || {});
field.component = [Component, componentProps];
field.component = [
(props) => (
<CollectionFieldContext.Provider value={collectionField}>
<Component {...props} />
</CollectionFieldContext.Provider>
),
componentProps,
];
}, [uiSchema]);
if (!uiSchema) {
return null;
}
return <Component {...props} />;
return null;
};
export const CollectionField = connect((props) => {

View File

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