Theme
Essentially theme is a simple function:
const fromRecord = (record) => (type) => record[type]const theme = fromRecord({ ...components })Component types
Section titled “Component types”All components can be divided into four logical types:
- components (generic UI element)
formsubmitButtonbuttonlayouttitlelabeldescriptionhelperrorsList
- widgets (input control)
textWidgetnumberWidgetselectWidgetcheckboxWidget
- templates (layout and presentation)
fieldTemplateobjectTemplateobjectPropertyTemplatearrayTemplatearrayItemTemplatemultiFieldTemplate
- fields (schema logic and orchestration)
stringFieldnumberFieldintegerFieldbooleanFieldobjectFieldarrayFieldtupleFieldnullFieldoneOfFieldanyOfFieldunknownField
Below are examples of the components required to render the following JSON schema:
{ "type": "string" }<script lang="ts"> ... const widgetType = "textWidget"
const Template = $derived(getComponent(ctx, "fieldTemplate", config)); const Widget = $derived(getComponent(ctx, widgetType, config));
const handlers = makeEventHandlers( ctx, () => config, () => validateField(ctx, config, value) ); const errors = $derived(getFieldErrors(ctx, config.path));</script>
<Template type="template" showTitle useLabel {widgetType} {value} {config} {errors}> <Widget type="widget" bind:value {config} {errors} {handlers} /></Template><script lang="ts"> ... const Layout = $derived(getComponent(ctx, "layout", config)); const TitleOrLabel = $derived( getComponent( ctx, (uiOption("useLabel") ?? useLabel) ? "label" : "title", config ) ); const Description = $derived(getComponent(ctx, "description", config)); const ErrorsList = $derived(getComponent(ctx, "errorsList", config)); const Help = $derived(getComponent(ctx, "help", config));
const { title, description, showMeta } = $derived( getTemplateProps(uiOption, config) ); const help = $derived(uiOption("help"));</script>
<Layout type="field" {config} {errors}> {#if showMeta && ((showTitle && title) || description)} <Layout type="field-meta" {config} {errors}> {#if showTitle && title} <Layout type="field-title-row" {config} {errors}> <TitleOrLabel {templateType} {title} {config} {errors} /> {@render action?.()} </Layout> {/if} {#if description} <Description {templateType} {description} {config} {errors} /> {/if} </Layout> {/if} <Layout type="field-content" {config} {errors}> {@render children()} </Layout> {#if errors.length > 0} <ErrorsList {errors} {config} /> {/if} {#if help !== undefined} <Help {help} {config} {errors} /> {/if}</Layout><script lang="ts"> ... const attributes = $derived( inputAttributes(ctx, config, "text", handlers, { type: "text", class: "sjsf-text" }) );</script>
<input bind:value {...attributes} /><Datalist id={attributes.list} {config} /><label {...labelAttributes(ctx, config, "labelAttributes", { class: "sjsf-label" })}> {title} {#if config.required} <span>*</span> {/if}</label>Foundational components
Section titled “Foundational components”The FoundationalComponentType is a subset of all components
(ComponentType) that can be explicitly used in form elements.
For example, we can use form as an argument for getComponent because
form is FoundationalComponentType:
<script lang="ts"> ... const Form = $derived(getComponent(ctx, "form", config));</script>
<Form bind:ref {config} {children} {attributes} />The main purpose of this list is to determine which components you can replace
using the ui:components property from UiSchema.
This is an extensible list, but by default it corresponds to the components listed in Component types.
Extra components
Section titled “Extra components”If the default set of components is insufficient, you can add the necessary components yourself.
The @sjsf/form library provides definitions and implementation of several extra
fields, as well as a set of definitions for extra widgets.
Fields
Section titled “Fields”Here is a list of extra fields that can be imported from @sjsf/form/fields/extra/*.
aggregatedarray-filesarray-native-filesarray-tagsboolean-selectenumfilefilesmulti-enumnative-filenative-filestagsunknown-native-file
To use them you can import them directly
import EnumField from "@sjsf/form/fields/extra/enum";or use an include import
import "@sjsf/form/fields/extra/enum-include";and replace the compatible field with it in uiSchema.
const uiSchema: UISchema = { "ui:components": { stringField: EnumField, // Or if you used the `include` import stringField: "enumField" }}Templates
Section titled “Templates”List of extra templates that can be imported from @sjsf/form/templates/extra/*.
optional-arrayoptional-fieldoptional-multi-fieldoptional-object
These templates are intended for rendering optional fields and differ from the original templates by the presence of the following condition:
{#if config.required || !isNil(value)} <Layout type="field-content" {config} {errors}> {@render children()} </Layout> {/if}Widgets
Section titled “Widgets”There are several types of extra widgets already defined in the library
(@sjsf/form/fields/extra-widgets/*):
aggregatedcheckboxescomboboxdate-pickerdate-range-pickerfilemulti-selectradio-buttonsradio(group)range-slider(two handles)rangeratingswitchtagstextarea
However, the ability to use them depends on the availability of a corresponding implementation in your chosen theme.