Form View Field Widgets
Learn how to create form view field widgets for the frontend of your application.
Overview
Form view widgets allow you to customize how fields are displayed in a form view.
They support both view mode and edit mode.
You can use either:
- Built-in widgets (provided by the framework), or
- Custom widgets (that you create).
Example: Display an integer field score as a slider using the built-in integerSlider widget.
Creating a Custom Widget
1. Create the Widget Component
Here’s an example of an integer slider widget. This widget allows users to select an integer value using a slider.
import { SolidFormFieldWidgetProps } from "@solidstarters/solid-core-ui/dist/types/solid-core";
export const SolidIntegerSliderStyleFormEditWidget = ({ formik, fieldContext }: SolidFormFieldWidgetProps) => {
const fieldMetadata = fieldContext.fieldMetadata;
const fieldLayoutInfo = fieldContext.field;
const fieldLabel = fieldLayoutInfo.attrs.label ?? fieldMetadata.displayName;
const showFieldLabel = fieldLayoutInfo?.attrs?.showLabel;
const min = fieldMetadata.min || 0;
const max = fieldMetadata.max || 5;
const fieldName = fieldLayoutInfo.attrs.name;
const currentValue = Number(formik.values[fieldName] ?? min);
const isFormFieldValid = (formik: any, fieldName: string) =>
formik.touched[fieldName] && formik.errors[fieldName];
return (
<div style={{ height: '60px' }}>
{showFieldLabel !== false && (
<div>
{fieldLabel}
{fieldMetadata.required && <span> *</span>}
</div>
)}
<div>
<Range
step={1}
min={min}
max={max}
values={[currentValue]}
onChange={(values) => {
formik.setFieldValue(fieldName, values[0]);
}}
renderTrack={({ props, children }) => {
const percent = ((currentValue - min) / (max - min)) * 100;
return (
<div {...props} style={{
...props.style,
height: "10px",
width: "100%",
borderRadius: "8px",
backgroundColor: "var(--primary-light-color)",
position: "relative"
}}>
<div style={{
position: "absolute",
height: "100%",
width: `${percent}%`,
backgroundColor: "var(--primary-color)",
borderRadius: "5px",
top: 0,
left: 0
}} />
{children}
</div>
)
}}
renderThumb={({ props }) => (
<div {...props} key={props.key} style={{
...props.style,
height: "18px",
width: "18px",
border: "4px solid var(--surface-0)",
borderRadius: '50%',
backgroundColor: "var(--primary-color)"
}} />
)}
/>
<div>
{Array.from({ length: max - min + 1 }, (_, i) => {
const num = i + min;
return (
<span key={num}>
{num === 0 ? '' : num}
</span>
);
})}
</div>
{isFormFieldValid(formik, fieldLayoutInfo.attrs.name) && (
<div>
</div>
)}
</div>
</div>
);
}File Path:
As per project structure, place the widget component in the extensions folder:
/solid-ui/app/admin/extensions/SolidIntegerSliderStyleFormEditWidget.tsx2. Register the Widget
Widgets must be registered in solid-extensions.ts:
File Path:
/solid-ui/app/admin/extensions/solid-extensions.ts3. Use in Layout
Now you can configure the widget within the form view layout configuration in the module metadata schema JSON file:
File Path:
/solid-api/module-metadata/<module-name>/<module-name>-metadata.json
How It Works
- SolidX loads the form layout in edit mode.
- It identifies fields with an
editWidget. - It dynamically imports the corresponding widget component.
- The widget is rendered with props of type
SolidFormFieldWidgetProps:
export type SolidFieldProps = { solidFormViewMetaData: any; // Metadata of the form view fieldMetadata: any, // Metadata of the specific field field: any, // Layout info of the field data: any, // Current data of the form modelName?: any, // Name of the model readOnly?: any, // Is the field read-only viewMode?: any // Is the form in view mode onChange?: any, // Callback for change events onBlur?: any, // Callback for blur events // Used in embedded views i.e for relation fields parentData?: any, // Data of the parent entity }
</details>
5. The widget then applies your **custom rendering logic**.
6. Default widgets are also rendered using the same mechanism.
## View Widgets (Read-Only Mode)
Similarly, you can create **view widgets** for **read-only mode** using `viewWidget` instead of `editWidget`.
### Example: Boolean View Widget
<details>
<summary>`CustomBooleanFormViewWidget`</summary>
```tsx
export const CustomBooleanFormViewWidget = ({ formik, fieldContext }: SolidFormFieldWidgetProps) => {
const fieldMetadata = fieldContext.fieldMetadata;
const fieldLayoutInfo = fieldContext.field;
const fieldLabel = fieldLayoutInfo.attrs.label ?? fieldMetadata.displayName;
return (
<div>
<p>{fieldLabel}</p>
<p>
{formik.values[fieldLayoutInfo.attrs.name] === true ||
formik.values[fieldLayoutInfo.attrs.name] === "true"
? "Yes" : "No"}
</p>
</div>
);
}This allows you to render a boolean field as "Yes/No" in view mode.
With this approach, you can seamlessly extend SolidX form views using custom widgets for both edit and view modes.