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.

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.

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 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.

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} ... />

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} ... />

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} ... />

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} ... />

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} ... />

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} ... />

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} />

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} />