Skip to main content

Custom Fields

Tushan comes pre-equipped with a wide variety of field types, such as: createXXXField()

However, developers often wish to implement their own components. This chapter will guide you on how to develop your own custom components.

In Tushan, a field is categorized into two main states: edit and detail. Therefore, by implementing these two states for a field, it can be used in almost all scenarios.

Tushan provides an out-of-the-box utility function createFieldFactory to help developers quickly implement these two states of a field:

import { createFieldFactory } from 'tushan';

export const createTextField = createFieldFactory({
detail: MyFieldDetail,
edit: MyFieldEdit,
});

For instance, if we want to implement a rich text editor, our pseudocode might look like this:

import { RichEditor, RichEditorViewer } from 'richeditor';
import React from 'react';
import {
createFieldFactory,
FieldDetailComponent,
FieldEditComponent,
} from 'tushan';

export const RichEditorFieldDetail: FieldDetailComponent<string> = React.memo(
(props) => {
return <RichEditorViewer>{props.value}</RichEditorViewer>;
}
);
RichEditorFieldDetail.displayName = 'RichEditorFieldDetail';

export const RichEditorFieldEdit: FieldEditComponent<string> = React.memo(
(props) => {
return (
<RichEditor
placeholder={props.options.edit?.placeholder ?? props.options.label}
value={props.value}
onChange={(val) => props.onChange(val)}
/>
);
}
);
RichEditorFieldEdit.displayName = 'RichEditorFieldEdit';

export const createRichEditorField = createFieldFactory({
detail: RichEditorFieldDetail,
edit: RichEditorFieldEdit,
});

In this example, assuming there's a richeditor library, we implement both the edit and detail forms of the field, handling data (value) and change callbacks through this hypothetical richeditor library.

We can also use props.options to access external inputs provided during creation for differentiated configuration.

When using our component, it can be invoked like any other basic field using createRichEditorField(source, options).

Accessing Context Information

Sometimes, when customizing fields, it's not only the field's properties that matter but also the need to consider the content of other fields in the record for some interactivity.

List and Detail Views

In list and detail views, we can use useRecordContext to access the context:

import { useRecordContext } from 'tushan';

export const MyField: FieldDetailComponent<string> = React.memo(
(props) => {
const record = useRecordContext();

return (
<div>{props.value}({record.id})</div>
);
}
);
MyField.displayName = 'MyField';

Edit View

In the edit view, we need to use the context provided by Form, a simple usage is as follows:

import { Form } from 'tushan';

export const MyField: FieldEditComponent<string> = React.memo(
(props) => {
const { form } = Form.useFormContext();
const id = Form.useWatch('id', form)

return (
<div>{props.value}({id})</div>
);
}
);
MyField.displayName = 'MyField';

Filter View

Currently, this is not supported. If needed, you can open an Issue to inform the developers.