Skip to main content

Form View Field Widgets

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.

Using Built-in Widget
{
"name": "model-form-view",
...
"layout": {
"type": "form",
...
"children": [
{
"type": "field",
"attrs": {
"name": "score",
"label": "Score",
"editWidget": "integerSlider"
}
}
]
}
}
tip

In the above example, the editWidget attribute specifies the widget to use in edit mode. While registering a widget, you can provide an alias (like integerSlider) to reference it easily in the layout instead of the full component name e.g. SolidIntegerSliderStyleFormEditWidget.

Built-in Widgets

SolidX ships with a set of pre-built widgets for every field type. You can reference these directly in the layout JSON without writing or registering any code.

Edit Widgets (editWidget)

Used in edit mode via the editWidget attribute on a form field.

Field TypeDescriptionWidget NameAlias
shortTextDefault single-line text inputDefaultShortTextFormEditWidget
shortTextPassword-style masked inputMaskedShortTextFormEditWidgetmaskedShortTextEdit
shortTextGoogle Material Symbols icon picker dialogSolidIconEditWidget
longTextDefault multi-line textareaDefaultLongTextFormEditWidget
longTextJSON editor with syntax highlightingDynamicJsonEditorFormEditWidgetjsonEditor
longTextCode editor with syntax highlightingCodeEditorFormEditWidgetcodeEditor
integerDefault number input for integersDefaultIntegerFormEditWidget
integerRange slider for integer valuesSolidIntegerSliderStyleFormEditWidgetintegerSlider
decimalDecimal number inputDefaultDecimalFormEditWidget
emailEmail input with format validationDefaultEmailFormEditWidget
passwordPassword input (edit mode)DefaultPasswordFormEditWidget
passwordPassword + confirm-password input (create mode)DefaultPasswordFormCreateWidget
timeTime pickerDefaultTimeFormEditWidget
dateDate picker (calendar)DefaultDateFormEditWidget
datetimeCombined date and time pickerDefaultDateTimeFormEditWidget
booleanDropdown select (Yes / No)DefaultBooleanFormEditWidgetbooleanSelectbox
booleanCheckbox styleSolidBooleanCheckboxStyleFormEditWidgetbooleanCheckbox
booleanToggle switch styleSolidBooleanSwitchStyleFormEditWidget
jsonJSON field editorDefaultJsonFormEditWidget
richTextWYSIWYG rich text editorDefaultRichTextFormEditWidget
selectionStaticAutocomplete dropdown for static optionsDefaultSelectionStaticAutocompleteFormEditWidget
selectionStaticRadio button groupSolidSelectionStaticRadioFormEditWidget
selectionStaticSegmented select buttonsSolidSelectionStaticSelectButtonFormEditWidget
selectionDynamicAutocomplete for API-driven dynamic optionsDefaultSelectionDynamicFormEditWidget
mediaSingleSingle file / image uploadDefaultMediaSingleFormEditWidget
mediaMultipleMultiple files / images uploadDefaultMediaMultipleFormEditWidget
relation.many2oneAutocomplete relation selectorDefaultRelationManyToOneFormEditWidget
relation.many2oneShort-text field wired to a many-to-one valuePseudoRelationManyToOneFormWidget
relation.many2manyMany-to-many autocomplete chipsDefaultRelationManyToManyAutoCompleteFormEditWidget
relation.many2manyCheckbox list for many-to-many selectionDefaultRelationManyToManyCheckBoxFormEditWidget
relation.many2manyToggle-switch grid for role permissionsRolePermissionsManyToManyFieldWidgetinputSwitch
relation.one2manyEmbedded editable table for one-to-manyDefaultRelationOneToManyFormEditWidget
relation.one2manyEmbedded list view of child records linked via a pseudo foreign-key relationshipPseudoRelationOneToManyFormWidget

View Widgets (viewWidget)

Used in view (read-only) mode via the viewWidget attribute on a form field.

Field TypeDescriptionWidget NameAlias
shortText, longText, emailDefault plain text displayDefaultShortTextFormViewWidget
shortTextMasked text displayMaskedShortTextFormViewWidgetmaskedShortTextForm
shortTextText with a colored initials avatarSolidShortTextFieldAvatarWidget
shortTextRenders a stored icon name as a Material Symbols iconSolidIconViewWidget
integerPlain integer displayDefaultIntegerFormViewWidget
decimalPlain decimal displayDefaultDecimalFormViewWidget
timeFormatted time displayDefaultTimeFormViewWidget
dateFormatted date displayDefaultDateFormViewWidget
datetimeFormatted date and time displayDefaultDateTimeFormViewWidget
booleanBoolean displayDefaultBooleanFormViewWidget
jsonJSON read-only displayDefaultJsonFormViewWidget
longTextRead-only JSON viewer with syntax highlightingDynamicJsonEditorFormViewWidgetjsonViewer
passwordMasked password displayDefaultPasswordFormViewWidget
richTextRendered rich text (HTML)DefaultRichTextFormViewWidget
selectionStaticStatic selection label displayDefaultSelectionStaticFormViewWidget
selectionDynamicDynamic selection label displayDefaultSelectionDynamicFormViewWidget
mediaSingleSingle media previewDefaultMediaSingleFormViewWidget
mediaMultipleMultiple media thumbnailsDefaultMediaMultipleFormViewWidget
relation.many2oneMany-to-one relation labelDefaultRelationManyToOneFormViewWidget
relationRelation value(s) rendered as avatar chipsSolidRelationFieldAvatarFormWidget
relation.one2manyRead-only embedded table for one-to-manyDefaultRelationOneToManyFormViewWidget

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.

SolidIntegerSliderStyleFormEditWidget
import { SolidFormFieldWidgetProps } from "@solidxai/core-ui";

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 className="w-full" style={{ height: '60px' }}>
{showFieldLabel !== false && (
<div className="font-medium mb-2">
{fieldLabel}
{fieldMetadata.required && <span className="text-red-500"> *</span>}
</div>
)}
<div className="relative h-12">
<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 className="flex align-item-center justify-content-between mt-2">
{Array.from({ length: max - min + 1 }, (_, i) => {
const num = i + min;
return (
<span key={num} className="text-sm">
{num === 0 ? '' : num}
</span>
);
})}
</div>
{isFormFieldValid(formik, fieldLayoutInfo.attrs.name) && (
<div className="absolute mt-2">
<Message severity="error" text={formik?.errors[fieldLayoutInfo.attrs.name]?.toString()} />
</div>
)}
</div>
</div>
);
}

File Path:

As per project structure, place the widget component in the extensions folder:

/solid-ui/src/extensions/<module-name>/<model-name>/custom-widgets/SolidIntegerSliderStyleFormEditWidget.tsx

2. Register the Widget

Widgets must be registered in solid-extensions.ts:

Registering the Widget
registerExtensionComponent(
"SolidIntegerSliderStyleFormEditWidget", // component name
SolidIntegerSliderStyleFormEditWidget, // component reference
["integerSlider"] // alias name
);

File Path:

/solid-ui/src/extensions/solid-extensions.ts

3. Use in Layout

Now you can configure the widget within the form view layout configuration in the module metadata schema JSON file:

Using Custom Widget in Layout
{
"name": "institute-form-view",
... // other attributes
"layout": {
"type": "form",
... // other attributes
"children": [
{
"type": "field",
"attrs": {
"name": "score",
"label": "Score",
"editWidget": "integerSlider"
}
}
]
}
}

File Path: /solid-api/module-metadata/<module-name>/<module-name>-metadata.json

How It Works

  1. SolidX loads the form layout in edit mode.
  2. It identifies fields with an editWidget.
  3. It dynamically imports the corresponding widget component.
  4. The widget is rendered with props of type SolidFormFieldWidgetProps:
SolidFormFieldWidgetProps
export type SolidFormFieldWidgetProps = {
formik: any; // Formik instance for form state management
fieldContext?: SolidFieldProps;
}

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
}

  1. The widget then applies your custom rendering logic.
  2. 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

CustomBooleanFormViewWidget
export const CustomBooleanFormViewWidget = ({ formik, fieldContext }: SolidFormFieldWidgetProps) => {
const fieldMetadata = fieldContext.fieldMetadata;
const fieldLayoutInfo = fieldContext.field;
const fieldLabel = fieldLayoutInfo.attrs.label ?? fieldMetadata.displayName;

return (
<div className="mt-2 flex-column gap-2">
<p className="m-0 form-field-label font-medium">{fieldLabel}</p>
<p className="m-0">
{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.