UI customization
Widgets customization
Section titled “Widgets customization”In addition to the predefined UI options,
each widget and theme component extends the UiOptions interface
with at least one property that allows customization.
For example, the textWidget from @sjsf/basic-theme
adds the property text?: HTMLInputAttributes.
By specifying it in the UI options,
you can control the widget’s attributes - even reactively.
<script lang="ts"> import { Content, createForm, setFormContext } from '@sjsf/form';
import * as defaults from "@/lib/form/defaults";
let width = $state(50)
const form = createForm({ ...defaults, schema: {type: 'string' }, uiSchema: { 'ui:options': { text: { get style() { return `flex-grow: 0; width: ${width}%` } } } } }) setFormContext(form)</script>
<input style="width: 100%;" type="range" bind:value={width} />
<Content />Check your theme page for an extended list of UI options:
Actions
Section titled “Actions”By specifying action?: FieldAction<SchemaValue | undefined> in the UI options,
your snippet will be rendered on the right side of the field header.
<script lang="ts"> import type { Ref } from '@sjsf/form/lib/svelte.svelte'; import { Content, createForm, setFormContext, type Config, type FieldErrors, type FormState } from '@sjsf/form';
import * as defaults from "@/lib/form/defaults";
const form = createForm({ ...defaults, schema: { type: "number" }, uiSchema: { 'ui:options': { title: "Number", action: randomInt } } }) setFormContext(form)</script>
{#snippet randomInt(_ctx: FormState<unknown>, _config: Config, valueRef: Ref<unknown>, _errors: FieldErrors)} <button type="button" onclick={() => { valueRef.current = Math.floor(Math.random() * 100) }}> Random </button>{/snippet}
<Content />
You can also use the prebuilt actions available in the @sjsf/form/fields/actions/* module:
clear-edit.sveltetoggles betweenundefinedand default valueclear.sveltesets value toundefineddisplay-primitive-value.sveltedisplays current value
UI options registry
Section titled “UI options registry”You can use UI options registry to ensure serializability of the UI schema.
To do this, you need to extend the UiOptionsRegistry interface and replace
the non-serializable value with registry:${key} in UiOptions.
Example:
import { createForm } from "@sjsf/form"import type { ItemTitle } from "@sjsf/form/fields/array/model";
declare module "@sjsf/form" { interface UiOptionsRegistry { myItemTitle: ItemTitle }}
const form = createForm({ ..., uiSchema: { "ui:options": { itemTitle: "registry:myItemTitle" } }, uiOptionsRegistry: { myItemTitle: (title, index) => `${title} [${index}]` }})Extra UI options
Section titled “Extra UI options”This property allows you to specify UI option for all components or compute it dynamically.
<script lang="ts"> import { chain, fromFactories, fromRecord } from '@sjsf/form/lib/resolver'; import { Content, createForm, setFormContext, type Config } from '@sjsf/form';
import * as defaults from "@/lib/form/defaults";
const form = createForm({ ...defaults, schema: { type: 'object', properties: { foo: { type: "string" }, bar: { type: "number" } } }, extraUiOptions: chain( fromRecord({ labelAttributes: { style: 'color: red' } }), fromFactories({ help: (config: Config) => `${config.path.at(-1)} help` }) ) }) setFormContext(form)</script>
<Content />