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.
Property reference
Section titled “Property reference”Required
Section titled “Required”formDef
Section titled “formDef”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} />// template:// <gui-form [config]="config"></gui-form>protected config = { formDef };// class field:config = { formDef };// render(): html`<gui-form .config=${this.config}></gui-form>`const config = { formDef };// <GuiForm :config="config" />const form = document.getElementById('app-form');form.config = { formDef };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} />import formDef from './my-form.json';
// template:// <gui-form [config]="config"></gui-form>protected config = { formDef };import formDef from './my-form.json';
// class field:config = { formDef };// render(): html`<gui-form .config=${this.config}></gui-form>`import formDef from './my-form.json';
const config = { formDef };// <GuiForm :config="config" />import formDef from './my-form.json';
const form = document.getElementById('app-form');form.config = { formDef };Top-level keys like "states" and per-widget suffixes ("label.someState") replace the Programmatic formConfig and selector-decorator paths.
Selectors and engine config
Section titled “Selectors and engine config”The Programmatic API has two dedicated wiring objects — formSelectors for behavior decorators, and formConfig for engine knobs. Both are typed and composable.
formSelectors
Section titled “formSelectors”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} />// template:// <gui-form [config]="config"></gui-form>protected config = { formDef, formSelectors };// class field:config = { formDef, formSelectors };// render(): html`<gui-form .config=${this.config}></gui-form>`const config = { formDef, formSelectors };// <GuiForm :config="config" />const form = document.getElementById('app-form');form.config = { formDef, formSelectors };formConfig
Section titled “formConfig”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} />// template:// <gui-form [config]="config"></gui-form>protected config = { formDef, formConfig };// class field:config = { formDef, formConfig };// render(): html`<gui-form .config=${this.config}></gui-form>`const config = { formDef, formConfig };// <GuiForm :config="config" />const form = document.getElementById('app-form');form.config = { formDef, formConfig };Putting it all together
Section titled “Putting it all together”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} />;}import { Component } from '@angular/core';import { CommonModule } from '@angular/common';import { gui } from '@golemui/gui-shared';import { FormComponent } from '@golemui/gui-angular';
@Component({ imports: [CommonModule, FormComponent], selector: 'app-my-form', template: `<gui-form [config]="config"></gui-form>`,})export class MyForm { protected config = { formDef: [ gui.inputs.textInput('name', { label: 'Name' }), gui.actions.button({ label: 'Submit', actionType: 'submit' }), ], formSelectors: [ gui.selectors.inputs({ suppressAutomaticPlaceholders: true }), ], formConfig: { validateOn: 'eager' as const }, };}import { LitElement, html } from 'lit';import { customElement } from 'lit/decorators.js';import { gui } from '@golemui/gui-shared';import '@golemui/gui-lit';
@customElement('my-form')export class MyForm extends LitElement { config = { formDef: [ gui.inputs.textInput('name', { label: 'Name' }), gui.actions.button({ label: 'Submit', actionType: 'submit' }), ], formSelectors: [ gui.selectors.inputs({ suppressAutomaticPlaceholders: true }), ], formConfig: { validateOn: 'eager' as const }, };
override createRenderRoot() { return this; }
override render() { return html`<gui-form .config=${this.config}></gui-form>`; }}<script setup lang="ts">import { gui } from '@golemui/gui-shared';import { GuiForm } from '@golemui/gui-vue';
const config = { formDef: [ gui.inputs.textInput('name', { label: 'Name' }), gui.actions.button({ label: 'Submit', actionType: 'submit' }), ], formSelectors: [ gui.selectors.inputs({ suppressAutomaticPlaceholders: true }), ], formConfig: { validateOn: 'eager' as const },};</script>
<template> <GuiForm :config="config" /></template>import '@golemui/gui-components/index.css';import '@golemui/gui-lit';import { gui } from '@golemui/gui-shared';
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' };
const form = document.getElementById('app-form');form.config = { formDef, formSelectors, formConfig };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, thevalidatorblock on each input. The form ships with its behavior baked in, which is convenient when the form definition lives in a CMS or backend. configobject props —customWidgetLoaders,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"] } } ]}Putting it all together
Section titled “Putting it all together”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} />;}import { Component } from '@angular/core';import { CommonModule } from '@angular/common';import { FormComponent } from '@golemui/gui-angular';import formDef from './my-form.json';import { CountryRenderer } from './renderers/country-renderer.component';import { allowedNames } from './validators/allowed-names';
@Component({ imports: [CommonModule, FormComponent], selector: 'app-my-form', template: `<gui-form [config]="config"></gui-form>`,})export class MyForm { protected config = { formDef, customWidgetLoaders: { productCard: async () => (await import('./widgets/product-card.component')).ProductCardComponent, }, itemRenderers: { countryRenderer: CountryRenderer }, customValidators: { allowedNames }, validateOn: 'eager' as const, };}import { LitElement, html } from 'lit';import { customElement } from 'lit/decorators.js';import '@golemui/gui-lit';import formDef from './my-form.json';import { countryRenderer } from './renderers/country-renderer';import { allowedNames } from './validators/allowed-names';
@customElement('my-form')export class MyForm extends LitElement { config = { formDef, customWidgetLoaders: { productCard: async () => (await import('./widgets/product-card.element')).ProductCardElement, }, itemRenderers: { countryRenderer }, customValidators: { allowedNames }, validateOn: 'eager' as const, };
override createRenderRoot() { return this; }
override render() { return html`<gui-form .config=${this.config}></gui-form>`; }}<script setup lang="ts">import { GuiForm } from '@golemui/gui-vue';import formDef from './my-form.json';import CountryRenderer from './renderers/CountryRenderer.vue';import { allowedNames } from './validators/allowed-names';
const config = { formDef, customWidgetLoaders: { productCard: async () => (await import('./widgets/ProductCard.vue')).default, }, itemRenderers: { countryRenderer: CountryRenderer }, customValidators: { allowedNames }, validateOn: 'eager' as const,};</script>
<template> <GuiForm :config="config" /></template>import '@golemui/gui-components/index.css';import '@golemui/gui-lit';import formDef from './my-form.json';import { countryRenderer } from './renderers/country-renderer';import { allowedNames } from './validators/allowed-names';
const form = document.getElementById('app-form');form.config = { formDef, customWidgetLoaders: { productCard: async () => (await import('./widgets/product-card.element')).ProductCardElement, }, itemRenderers: { countryRenderer }, customValidators: { allowedNames }, validateOn: 'eager',};Data inputs
Section titled “Data inputs”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} />// template:// <gui-form [config]="config"></gui-form>protected config = { formDef, data: { username: 'golemui', email: 'hello@example.com' } };// class field:config = { formDef: this.formDef, data: { username: 'golemui', email: 'hello@example.com' },};// render(): html`<gui-form .config=${this.config}></gui-form>`const formData = { username: 'golemui', email: 'hello@example.com' };const config = { formDef, data: formData };// <GuiForm :config="config" />const formData = { username: 'golemui', email: 'hello@example.com' };const form = document.getElementById('app-form');form.config = { formDef, data: formData };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} />// template:// <gui-form [config]="config"></gui-form>protected config = { formDef, meta: { tenantId: 'acme-co', sessionId: 'abc-123' } };// class field:config = { formDef: this.formDef, meta: { tenantId: 'acme-co', sessionId: 'abc-123' },};// render(): html`<gui-form .config=${this.config}></gui-form>`const formMeta = { tenantId: 'acme-co', sessionId: 'abc-123' };const config = { formDef, data: formData, meta: formMeta };// <GuiForm :config="config" />const formMeta = { tenantId: 'acme-co', sessionId: 'abc-123' };const form = document.getElementById('app-form');form.config = { formDef, data: formData, meta: formMeta };Engine wiring
Section titled “Engine wiring”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.
Widget loaders
Section titled “Widget loaders”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} ... />protected formConfig = { widgetLoaders: { productCard: async () => (await import('./product-card.component')).ProductCardComponent, },};// <gui-form [config]="config"></gui-form>formConfig = { widgetLoaders: { productCard: async () => (await import('./product-card.element')).ProductCardElement, },};// html`<gui-form .config=${this.config}></gui-form>`const formConfig = { widgetLoaders: { productCard: async () => (await import('./ProductCard.vue')).default, },};// <GuiForm :config="config" />const formConfig = { widgetLoaders: { productCard: async () => (await import('./product-card.element')).ProductCardElement, },};// const form = document.getElementById('app-form');// form.config = { formDef, formConfig };Pass it as customWidgetLoaders in the config object:
const customWidgetLoaders = { productCard: async () => (await import('./ProductCard')).ProductCard,};// <GuiForm config={config} ... />protected customWidgetLoaders = { productCard: async () => (await import('./product-card.component')).ProductCardComponent,};// <gui-form [config]="config"></gui-form>customWidgetLoaders = { productCard: async () => (await import('./product-card.element')).ProductCardElement,};// html`<gui-form .config=${this.config}></gui-form>`const customWidgetLoaders = { productCard: async () => (await import('./ProductCard.vue')).default,};// <GuiForm :config="config" />const customWidgetLoaders = { productCard: async () => (await import('./product-card.element')).ProductCardElement,};// const form = document.getElementById('app-form');// form.config = { formDef, customWidgetLoaders };See Features / Widget Loaders.
Item renderers
Section titled “Item renderers”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} ... />import { CountryRenderer } from './country-renderer.component';
protected formConfig = { itemRenderers: { countryRenderer: CountryRenderer },};// <gui-form [config]="config"></gui-form>import { countryRenderer } from './country-renderer';
formConfig = { itemRenderers: { countryRenderer },};// html`<gui-form .config=${this.config}></gui-form>`import CountryRenderer from './CountryRenderer.vue';
const formConfig = { itemRenderers: { countryRenderer: CountryRenderer },};// <GuiForm :config="config" />import { countryRenderer } from './country-renderer';
const formConfig = { itemRenderers: { countryRenderer },};// const form = document.getElementById('app-form');// form.config = { formDef, formConfig };Pass it as itemRenderers in the config object:
import { CountryRenderer } from './CountryRenderer';
const itemRenderers = { countryRenderer: CountryRenderer };// <GuiForm config={config} ... />import { CountryRenderer } from './country-renderer.component';
protected itemRenderers = { countryRenderer: CountryRenderer };// <gui-form [config]="config"></gui-form>import { countryRenderer } from './country-renderer';
itemRenderers = { countryRenderer };// html`<gui-form .config=${this.config}></gui-form>`import CountryRenderer from './CountryRenderer.vue';
const itemRenderers = { countryRenderer: CountryRenderer };// <GuiForm :config="config" />import { countryRenderer } from './country-renderer';
const itemRenderers = { countryRenderer };// const form = document.getElementById('app-form');// form.config = { formDef, itemRenderers };See Features / Item Renderers.
Custom validators
Section titled “Custom validators”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} ... />import { allowedNames } from './validators/allowed-names';
protected formConfig = { customValidators: { allowedNames },};// <gui-form [config]="config"></gui-form>import { allowedNames } from './validators/allowed-names';
formConfig = { customValidators: { allowedNames },};// html`<gui-form .config=${this.config}></gui-form>`import { allowedNames } from './validators/allowed-names';
const formConfig = { customValidators: { allowedNames },};// <GuiForm :config="config" />import { allowedNames } from './validators/allowed-names';
const formConfig = { customValidators: { allowedNames },};// const form = document.getElementById('app-form');// form.config = { formDef, formConfig };Pass it as customValidators in the config object:
import { allowedNames } from './validators/allowed-names';
const customValidators = { allowedNames };// <GuiForm config={config} ... />import { allowedNames } from './validators/allowed-names';
protected customValidators = { allowedNames };// <gui-form [config]="config"></gui-form>import { allowedNames } from './validators/allowed-names';
customValidators = { allowedNames };// html`<gui-form .config=${this.config}></gui-form>`import { allowedNames } from './validators/allowed-names';
const customValidators = { allowedNames };// <GuiForm :config="config" />import { allowedNames } from './validators/allowed-names';
const customValidators = { allowedNames };// const form = document.getElementById('app-form');// form.config = { formDef, customValidators };See Extending GolemUI / Validators.
Validation timing
Section titled “Validation timing”When validation runs. Accepts a single mode or an array combining the latter three:
type ValidateOn = | 'eager' | 'change' | 'blur' | 'submit' | ('change' | 'blur' | 'submit')[];| Mode | Triggers 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} ... />import type { ValidateOn } from '@golemui/core';
protected formConfig = { validateOn: 'change' as ValidateOn,};// <gui-form [config]="config"></gui-form>import type { ValidateOn } from '@golemui/core';
formConfig = { validateOn: 'change' as ValidateOn,};// html`<gui-form .config=${this.config}></gui-form>`const formConfig = { validateOn: 'change' as const };// <GuiForm :config="config" />const formConfig = { validateOn: 'change' };// const form = document.getElementById('app-form');// form.config = { formDef, formConfig };Pass it as validateOn in the config object:
const config = { formDef, validateOn: 'change' as const };// <GuiForm config={config} />import type { ValidateOn } from '@golemui/core';
// template:// <gui-form [config]="config"></gui-form>protected config = { formDef, validateOn: 'change' as ValidateOn };import type { ValidateOn } from '@golemui/core';
// class field:config = { formDef: this.formDef, validateOn: 'change' as ValidateOn };// render(): html`<gui-form .config=${this.config}></gui-form>`const config = { formDef, validateOn: 'change' as const };// <GuiForm :config="config" />const form = document.getElementById('app-form');form.config = { formDef, validateOn: 'change' };Dependencies
Section titled “Dependencies”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} ... />import snarkdown from 'snarkdown';
protected formConfig = { dependencies: { markdown: { parse: snarkdown } },};// <gui-form [config]="config"></gui-form>import snarkdown from 'snarkdown';
formConfig = { dependencies: { markdown: { parse: snarkdown } },};// html`<gui-form .config=${this.config}></gui-form>`import snarkdown from 'snarkdown';
const formConfig = { dependencies: { markdown: { parse: snarkdown } },};// <GuiForm :config="config" />import snarkdown from 'snarkdown';
const formConfig = { dependencies: { markdown: { parse: snarkdown } },};// const form = document.getElementById('app-form');// form.config = { formDef, formConfig };Pass it as dependencies in the config object:
import snarkdown from 'snarkdown';
const dependencies = { markdown: { parse: snarkdown } };// <GuiForm config={config} ... />import snarkdown from 'snarkdown';
protected dependencies = { markdown: { parse: snarkdown } };// <gui-form [config]="config"></gui-form>import snarkdown from 'snarkdown';
dependencies = { markdown: { parse: snarkdown } };// html`<gui-form .config=${this.config}></gui-form>`import snarkdown from 'snarkdown';
const dependencies = { markdown: { parse: snarkdown } };// <GuiForm :config="config" />import snarkdown from 'snarkdown';
const dependencies = { markdown: { parse: snarkdown } };// const form = document.getElementById('app-form');// form.config = { formDef, dependencies };States
Section titled “States”Named boolean expressions evaluated against $form.
Place the map inside formConfig.states:
const formConfig = { states: { hasDiscount: '$form.hasDiscountCode === true', },};// <GuiForm config={config} ... />protected formConfig = { states: { hasDiscount: '$form.hasDiscountCode === true', },};// <gui-form [config]="config"></gui-form>formConfig = { states: { hasDiscount: '$form.hasDiscountCode === true', },};// html`<gui-form .config=${this.config}></gui-form>`const formConfig = { states: { hasDiscount: '$form.hasDiscountCode === true', },};// <GuiForm :config="config" />const formConfig = { states: { hasDiscount: '$form.hasDiscountCode === true', },};// const form = document.getElementById('app-form');// form.config = { formDef, formConfig };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.
Other inputs
Section titled “Other inputs”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.
localization
Section titled “localization”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} /><gui-form [config]="config"></gui-form>html`<gui-form .config=${this.config}></gui-form>`;const config = { formDef, data: formData, formConfig, localization };// <GuiForm :config="config" />const form = document.getElementById('app-form');form.config = { formDef, data: formData, formConfig, localization };Include localization in the config object alongside the other engine-wiring props:
const config = { formDef, data: formData, customWidgetLoaders, localization };// <GuiForm config={config} /><gui-form [config]="config"></gui-form>html`<gui-form .config=${this.config}></gui-form>`;const config = { formDef, data: formData, customWidgetLoaders, localization };// <GuiForm :config="config" />const form = document.getElementById('app-form');form.config = { formDef, data: formData, customWidgetLoaders, localization };middlewares
Section titled “middlewares”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} />import { devToolsMiddleware } from '@golemui/core';
// template:// <gui-form [config]="config"></gui-form>protected config = { formDef, middlewares: [devToolsMiddleware()] };import { devToolsMiddleware } from '@golemui/core';
// class field:config = { formDef: this.formDef, middlewares: [devToolsMiddleware()],};// render(): html`<gui-form .config=${this.config}></gui-form>`import { devToolsMiddleware } from '@golemui/core';
const middlewares = [devToolsMiddleware()];const config = { formDef, data: formData, middlewares };// <GuiForm :config="config" />import { devToolsMiddleware } from '@golemui/core';
const middlewares = [devToolsMiddleware()];const form = document.getElementById('app-form');form.config = { formDef, data: formData, middlewares };autocomplete
Section titled “autocomplete”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" /><gui-form [config]="config" [autocomplete]="'off'"></gui-form>html`<gui-form .config=${this.config} .autocomplete=${'off'}></gui-form>`;<GuiForm :config="config" autocomplete="off" />const form = document.getElementById('app-form');form.config = { formDef };form.setAttribute('autocomplete', 'off');formName
Section titled “formName”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} />// template:// <gui-form [config]="config"></gui-form>protected config = { formDef, formName: 'checkout' };// class field:config = { formDef: this.formDef, formName: 'checkout' };// render(): html`<gui-form .config=${this.config}></gui-form>`const config = { formDef, formName: 'checkout' };// <GuiForm :config="config" />const form = document.getElementById('app-form');form.config = { formDef, formName: 'checkout' };Form Callbacks
Section titled “Form Callbacks”formEvent
Section titled “formEvent”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} />import type { FormEvent } from '@golemui/core';
// template:// <gui-form [config]="config" (formEvent)="onFormEvent($event)"></gui-form>protected onFormEvent(event: FormEvent) { if (event.name === 'submit') { console.log('Submit:', event.data); }}import type { FormEvent } from '@golemui/core';
onFormEvent(event: FormEvent) { if (event.name === 'submit') { console.log('Submit:', event.data); }}
// render():html`<gui-form .config=${this.config} @formEvent=${(e: CustomEvent<FormEvent>) => this.onFormEvent(e.detail)}></gui-form>`;<script setup lang="ts">import type { FormEvent } from '@golemui/core';import { GuiForm } from '@golemui/gui-vue';
const config = { formDef, data: formData };
function onFormEvent(event: FormEvent) { if (event.name === 'submit') { console.log('Submit:', event.data); }}</script>
<template> <GuiForm :config="config" @form-event="onFormEvent" /></template>import '@golemui/gui-components/index.css';import '@golemui/gui-lit';
function onFormEvent(event) { if (event.name === 'submit') { console.log('Submit:', event.data); }}
const form = document.getElementById('app-form');form.config = { formDef, data: formData };form.addEventListener('formEvent', (e) => onFormEvent(e.detail));formHealth
Section titled “formHealth”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} />import type { FormHealth } from '@golemui/core';
// template:// <gui-form [config]="config" (formHealth)="onFormHealth($event)"></gui-form>protected onFormHealth(health: FormHealth) { console.log('Health:', health.status);}import type { FormHealth } from '@golemui/core';
onFormHealth(health: FormHealth) { console.log('Health:', health.status);}
// render():html`<gui-form .config=${this.config} @formHealth=${(e: CustomEvent<FormHealth>) => this.onFormHealth(e.detail)}></gui-form>`;<script setup lang="ts">import type { FormHealth } from '@golemui/core';import { GuiForm } from '@golemui/gui-vue';
const config = { formDef, data: formData };
function onFormHealth(health: FormHealth) { console.log('Health:', health.status);}</script>
<template> <GuiForm :config="config" @form-health="onFormHealth" /></template>import '@golemui/gui-components/index.css';import '@golemui/gui-lit';
function onFormHealth(health) { console.log('Health:', health.status);}
const form = document.getElementById('app-form');form.config = { formDef, data: formData };form.addEventListener('formHealth', (e) => onFormHealth(e.detail));