Skip to content

Configuration

This page is the canonical reference for every input the form component accepts. The same surface ships in React, Angular, Lit, Vue, and Vanilla JS — only the binding syntax differs (prop={...} for React, [prop]="..." for Angular, .prop=${...} for Lit, :prop="..." for Vue, element.prop = ... for Vanilla JS). For the framework-typed signatures, see React, Angular, Lit, Vue, Vanilla JS.

You’re looking at the Programmatic view. The Programmatic API leans on formSelectors and formConfig to wire the engine — you’ll see those everywhere below. Switch to the JSON view from the language selector to see the same props described from the JSON form’s perspective.

You’re looking at the JSON view. JSON forms don’t use formSelectors or formConfig — every engine-wiring input below is passed as a standalone component prop. Switch to the Programmatic view to see the gui.* / formConfig equivalents.

A Programmatic array of gui.* shortcuts. Composed with gui.inputs.*, gui.layouts.*, gui.actions.*, gui.displays.* and resolved through the DX pipeline at render time.

import { gui } from '@golemui/gui-shared';
const formDef = [
gui.inputs.textInput('name', { label: 'Name' }),
gui.actions.button({ label: 'Submit', actionType: 'submit' }),
];

Wire it to the form component:

const config = { formDef };
// <GuiForm config={config} />

See Form Definition API.

A parsed JSON form definition. Loaded from a file, fetched from an API, or authored as a literal in your code.

{
"form": [
{ "kind": "input", "type": "textinput", "path": "name", "label": "Name" },
{ "kind": "action", "type": "button", "label": "Submit", "on": { "click": "submit" } }
]
}

Wire it to the form component:

import formDef from './my-form.json';
const config = { formDef };
// <GuiForm config={config} />

Top-level keys like "states" and per-widget suffixes ("label.someState") replace the Programmatic formConfig and selector-decorator paths.

The Programmatic API has two dedicated wiring objects — formSelectors for behavior decorators, and formConfig for engine knobs. Both are typed and composable.

GSL selector decorators that apply by widget type, tag, or uid. Built with gui.selectors.* and resolved against your formDef array at render time. See Selectors.

import { gui } from '@golemui/gui-shared';
const formSelectors = [
gui.selectors.inputs({ suppressAutomaticPlaceholders: true }),
gui.selectors.tag('identity').inputs({ autocomplete: 'off' }),
];

Wire it alongside formDef:

const config = { formDef, formSelectors };
// <GuiForm config={config} />

DX engine wiring container. Holds widgetLoaders, itemRenderers, dependencies, validateOn, customValidators, states, suppressAutomaticStack. The Programmatic API treats formConfig as the single home for all of these knobs.

const formConfig = {
widgetLoaders: {
productCard: async () => (await import('./ProductCard')).ProductCard,
},
itemRenderers: { countryRenderer },
dependencies: { markdown: { parse: snarkdown } },
validateOn: 'eager',
states: {
hasDiscount: '$form.hasDiscountCode === true',
},
};

Wire it alongside formDef:

const config = { formDef, formConfig };
// <GuiForm config={config} />

A complete component skeleton wiring formDef, formSelectors, and formConfig together — copy this as the starting shape for your own form:

import { gui } from '@golemui/gui-shared';
import { GuiForm } from '@golemui/gui-react';
const formDef = [
gui.inputs.textInput('name', { label: 'Name' }),
gui.actions.button({ label: 'Submit', actionType: 'submit' }),
];
const formSelectors = [
gui.selectors.inputs({ suppressAutomaticPlaceholders: true }),
];
const formConfig = { validateOn: 'eager' as const };
const config = { formDef, formSelectors, formConfig };
export function MyForm() {
return <GuiForm config={config} />;
}

The JSON path expresses the same behaviors inline on the form itself and as standalone component props — there’s no formSelectors or formConfig wrapper to compose. Each path has its own ergonomics:

  • Inline on the JSON"states" at the form root, "label.someState" suffixes on widget props for per-state overrides, the validator block on each input. The form ships with its behavior baked in, which is convenient when the form definition lives in a CMS or backend.
  • config object propscustomWidgetLoaders, itemRenderers, customValidators, dependencies, validateOn. These stay in your application code, which keeps secrets, framework imports, and platform-specific renderers out of the form payload.

A typical JSON form with state-driven behavior:

{
"states": {
"hasDiscount": "$form.hasDiscountCode === true"
},
"form": [
{
"kind": "input",
"type": "textinput",
"path": "discountCode",
"label": "Discount code",
"label.hasDiscount": "Your discount code",
"include": { "in": ["hasDiscount"] }
}
]
}

A complete component skeleton wiring a JSON formDef plus the standalone engine-wiring props — copy this as the starting shape for your own JSON-driven form. The widget loader, renderer, and validator below are the same shapes used in the Programmatic example; only the wiring differs.

import { GuiForm } from '@golemui/gui-react';
import formDef from './my-form.json';
import { CountryRenderer } from './renderers/CountryRenderer';
import { allowedNames } from './validators/allowed-names';
const config = {
formDef,
customWidgetLoaders: {
productCard: async () => (await import('./widgets/ProductCard')).ProductCard,
},
itemRenderers: { countryRenderer: CountryRenderer },
customValidators: { allowedNames },
validateOn: 'eager' as const,
};
export function MyForm() {
return <GuiForm config={config} />;
}

The initial form data object. Reads/writes flow through the engine’s reactive store; the value here only seeds the first render.

const formData = { username: 'golemui', email: 'hello@example.com' };
const config = { formDef, data: formData };
// <GuiForm config={config} />

Optional out-of-band metadata you want to thread through events and state. The engine doesn’t interpret it; you read it back from event.data / via custom widgets.

const formMeta = { tenantId: 'acme-co', sessionId: 'abc-123' };
const config = { formDef, data: formData, meta: formMeta };
// <GuiForm config={config} />

The next group of properties wires the engine — widget loaders, item renderers, custom validators, validation timing, dependencies, and states. They mean exactly the same thing in both paths; what differs is where you put them.

With the Programmatic API, the typical home for these knobs is formConfig — a typed object you nest inside the config prop. The top-level config properties (customWidgetLoaders, itemRenderers, etc.) also accept these knobs directly and merge with whatever you put in formConfig, which is handy when you want to keep environment-specific bits out of the resolved form.

With the JSON path, each knob is a property on the config object — customWidgetLoaders, itemRenderers, customValidators, validateOn, dependencies. They live in your application code rather than in the form payload, which is exactly what you want when the JSON itself is loaded from a CMS, an API, or a backend.

Map of widget type → async loader. Merged with the framework’s default widget set.

Place it inside formConfig.widgetLoaders:

const formConfig = {
widgetLoaders: {
productCard: async () => (await import('./ProductCard')).ProductCard,
},
};
// <GuiForm config={config} ... />

Pass it as customWidgetLoaders in the config object:

const customWidgetLoaders = {
productCard: async () => (await import('./ProductCard')).ProductCard,
};
// <GuiForm config={config} ... />

See Features / Widget Loaders.

Map of renderer name → framework-specific component. Referenced from a widget’s itemRenderer prop (dropdown, list, radiogroup).

Place it inside formConfig.itemRenderers:

import { CountryRenderer } from './CountryRenderer';
const formConfig = {
itemRenderers: { countryRenderer: CountryRenderer },
};
// <GuiForm config={config} ... />

Pass it as itemRenderers in the config object:

import { CountryRenderer } from './CountryRenderer';
const itemRenderers = { countryRenderer: CountryRenderer };
// <GuiForm config={config} ... />

See Features / Item Renderers.

Map of validator name → schema factory. Referenced from a widget’s validator: { type: 'custom', <name>: <config> }. The factory follows the CustomValidatorSchemaFn interface and returns a schema (typically a Zod check):

import type { CustomValidatorSchemaFn } from '@golemui/core';
import { z } from 'zod';
export const allowedNames: CustomValidatorSchemaFn = (names: string[]) =>
z.string().check(
z.superRefine((val, ctx) => {
if (val && names.includes(val) === false) {
ctx.addIssue({
code: 'custom',
message: `Name "${val}" not in ${names.map((n) => `"${n}"`).join(', ')}`,
input: val,
});
}
}),
);

Place it inside formConfig.customValidators:

import { allowedNames } from './validators/allowed-names';
const formConfig = {
customValidators: { allowedNames },
};
// <GuiForm config={config} ... />

Pass it as customValidators in the config object:

import { allowedNames } from './validators/allowed-names';
const customValidators = { allowedNames };
// <GuiForm config={config} ... />

See Extending GolemUI / Validators.

When validation runs. Accepts a single mode or an array combining the latter three:

type ValidateOn =
| 'eager'
| 'change'
| 'blur'
| 'submit'
| ('change' | 'blur' | 'submit')[];
ModeTriggers when
'change'The user changes the field value
'blur'The user leaves the field
'submit'A submit event is emitted (all fields are touched first)
'eager'Any of the above happens (default)

Place it inside formConfig.validateOn:

const formConfig = { validateOn: 'change' };
// <GuiForm config={config} ... />

Pass it as validateOn in the config object:

const config = { formDef, validateOn: 'change' as const };
// <GuiForm config={config} />

External helpers that widgets read at render time. Today, the only built-in widgets that need a dependency are Markdown and Markdown Text — both expect a markdown.parse function for live preview rendering.

Place it inside formConfig.dependencies:

import snarkdown from 'snarkdown';
const formConfig = {
dependencies: { markdown: { parse: snarkdown } },
};
// <GuiForm config={config} ... />

Pass it as dependencies in the config object:

import snarkdown from 'snarkdown';
const dependencies = { markdown: { parse: snarkdown } };
// <GuiForm config={config} ... />

See Features / Dependencies.

Named boolean expressions evaluated against $form.

Place the map inside formConfig.states:

const formConfig = {
states: {
hasDiscount: '$form.hasDiscountCode === true',
},
};
// <GuiForm config={config} ... />

At the JSON form root — the form payload itself carries the state map, so the wiring is the same regardless of framework:

{
"states": {
"hasDiscount": "$form.hasDiscountCode === true"
},
"form": [...]
}

See Features / States.

The next four inputs apply equally to Programmatic and JSON forms. localization, middlewares, and formName sit inside the config object; autocomplete is a direct component attribute.

Translator implementing the I18nTranslator interface from @golemui/core. Resolves Localizable shapes ({ key, default, params }) on labels, placeholders, hints, validator messages, and section labels. Enables RTL automatically when the active language is RTL. See Features / i18n for translator implementations and the Responsive & RTL guide for RTL details.

Include localization in the config object alongside formDef and formConfig:

const config = { formDef, data: formData, formConfig, localization };
// <GuiForm config={config} />

Include localization in the config object alongside the other engine-wiring props:

const config = { formDef, data: formData, customWidgetLoaders, localization };
// <GuiForm config={config} />

Array of Middleware functions wrapping the form’s reactive store — used for logging, persistence, devtools. See Features / Middlewares.

import { devToolsMiddleware } from '@golemui/core';
const middlewares = [devToolsMiddleware()];
const config = { formDef, data: formData, middlewares };
// <GuiForm config={config} />

Sets the underlying <form> element’s autocomplete attribute. Useful to disable browser autofill across the entire form. Individual input widgets also accept an autocomplete prop (via props) for fine-grained control using any W3C autofill token (e.g. 'given-name', 'street-address', 'off').

const config = { formDef };
// <GuiForm config={config} autocomplete="off" />

Optional form identifier. Useful when you have several <gui-form> instances on the same page and want to disambiguate them in event payloads or middleware logs.

const config = { formDef, formName: 'checkout' };
// <GuiForm config={config} />

Fired when a widget fires a wired event (onClick, onChange, onLoad, onFilter, onBlur). Payload: { name, data, detail }. See Features / Form Events.

import type { FormEvent } from '@golemui/core';
function handleFormEvent(event: FormEvent) {
if (event.name === 'submit') {
console.log('Submit:', event.data);
}
}
const config = { formDef, data: formData };
// <GuiForm config={config} formEvent={handleFormEvent} />

Fired when the form’s validation status changes. Payload: { status: 'ok' | 'errored', message? }. Wire it to disable a submit button or surface a banner.

import type { FormHealth } from '@golemui/core';
function handleFormHealth(health: FormHealth) {
console.log('Health:', health.status);
}
const config = { formDef, data: formData };
// <GuiForm config={config} formHealth={handleFormHealth} />