Custom JsonForms control
Register a custom renderer, cell, or plugin translation for node property panels.
Node properties render through JsonForms. Plug in a custom React component for any property type — colour picker, code editor, file uploader — by registering a renderer through the jsonForm prop on <WorkflowBuilder.Root>.
WorkflowBuilderJsonFormConfig
Section titled “WorkflowBuilderJsonFormConfig”interface WorkflowBuilderJsonFormConfig { renderers?: JsonFormsRendererExtension[]; cells?: JsonFormsCellExtension[]; translations?: PluginTranslationResource;}
type JsonFormsRendererExtension = JsonFormsRendererRegistryEntry; // from @jsonforms/coretype JsonFormsCellExtension = JsonFormsCellRendererRegistryEntry; // from @jsonforms/coreConsumer-supplied renderers are tried before the built-ins. When two testers return the same rank, yours wins — that’s how you override a built-in control.
Custom renderer — full example
Section titled “Custom renderer — full example”import { type JsonFormsRendererRegistryEntry, rankWith, uiTypeIs } from '@jsonforms/core';import { withJsonFormsControlProps } from '@jsonforms/react';import { WorkflowBuilder } from '@workflowbuilder/sdk';
import '@workflowbuilder/sdk/style.css';
function ColorPicker({ data, handleChange, path,}: { data: string; handleChange: (path: string, value: string) => void; path: string;}) { return <input type="color" value={data ?? '#000000'} onChange={(e) => handleChange(path, e.target.value)} />;}
const colorPickerRenderer: JsonFormsRendererRegistryEntry = { tester: rankWith(5, uiTypeIs('ColorPicker')), renderer: withJsonFormsControlProps(ColorPicker),};
function App() { return ( <WorkflowBuilder.Root jsonForm={{ renderers: [colorPickerRenderer] }} integration={{ strategy: 'props', onDataSave }} /> );}Any node whose uischema contains { type: 'ColorPicker', scope: '...' } will now render with your ColorPicker component.
cells work the same way — use JsonFormsCellRendererRegistryEntry for list/array cell rendering. Built-in cells are passed through when consumer cells are absent; if you provide any, yours are used as-is (no merging with built-ins for cells).
Translations
Section titled “Translations”type PluginTranslationResource = { [lang: string]: { translation: { [key: string]: { [key: string]: string | { [key: string]: string }; }; }; };};Translations are merged into the plugins.* namespace of the built-in i18n resources.
<WorkflowBuilder.Root jsonForm={{ translations: { en: { translation: { plugins: { colorPicker: { label: 'Pick a color', description: 'Choose any color for the node', }, }, }, }, }, }} integration={{ strategy: 'props', onDataSave }}/>The same translations can also be registered imperatively via registerPluginTranslation.
Related types
Section titled “Related types”Available via import type { ... } from '@workflowbuilder/sdk':
WorkflowBuilderJsonFormConfigJsonFormsRendererExtensionJsonFormsCellExtensionPluginTranslationResourceUISchema— for typing youruischema.ts. Built-in element types are listed in Form overview.