Skip to content
Forms, switch product

Framework form components

Once your widget set has an authoring pipeline, one factory call per framework turns it into the equivalent of <GuiForm> / <gui-form>. React, Vue, and Lit expose createFormComponent; Angular uses dependency injection instead, with provideWidgetSet and a generic host component. The shipped gui components are built with exactly these calls, so every example below is the real source of a published package.

All four factories take the same contract:

interface WidgetSetDefinition {
/** type -> async component loader. Must include the reserved `flex` and `repeater` entries. */
widgetLoaders: WidgetLoaders;
/** validator factory; receives the form's customValidators */
validators: (customValidators?) => ValidatorFn;
/** produced by createImplementation; omit for a JSON-only widget set */
resolveFormInput?: ResolveFormInputFn;
/** widget set defaults, lowest merge precedence */
dependencies?: Dependencies;
}

The framework factories keep only framework concerns (refs, emits, signals, custom element wiring). Everything else, resolving the form input and the config merge rules, is shared, so the four hosts cannot drift apart:

ConfigMerge order (last wins)
widget loaderswidget set built-ins, then DX-provided loaders, then the form’s customWidgetLoaders
dependencieswidget set defaults, then DX-provided, then the form’s
functions, item renderersDX-provided, then the form’s
validateOnthe form’s setting, then DX-provided, then 'eager'

createFormComponent returns a forwardRef component with the usual props (config, autocomplete, formEvent, formSubmit, formHealth, formHealthBoundary) and an imperative handle (setData, setMeta). This is the complete source of GuiForm in @golemui/gui-react:

import { createFormComponent } from '@golemui/react';
import { type GuiFormInitConfig } from '@golemui/gui-shared';
import { initValidators } from '@golemui/gui-validators';
import { widgetLoaders } from './widget.loaders';
export const GuiForm = createFormComponent<GuiFormInitConfig>({
widgetLoaders,
validators: initValidators,
resolveFormInput,
});
GuiForm.displayName = 'GuiForm';

The form bundle is memoized on the config reference, and handlers registered through the DX definitions are chained with your formEvent prop so both fire.

The contract is granular, so you can mix: widgetLoaders is a public export of each @golemui/gui-react / gui-vue / gui-lit / gui-angular package and initValidators of @golemui/gui-validators. A widget set that only swaps validators, or only adds loaders on top of the gui widgets, is a three-line definition rather than a fork.

A JSON-only widget set (no TS authoring namespace) simply omits resolveFormInput: JSON definitions pass through the decoder without the DX pipeline. For such a set the schema tree is the whole authoring story, so it is worth publishing one.