The component registry is the lookup system that maps a component string in a UINode to an actual Vue component implementation. Every component available in V2 forms is registered in the global registry with a namespace, type, category, and implementation. When the SchemaNode renderer encounters a component value, it resolves it through the registry to find the matching component.
This page documents how the registry works, lists all available built-in components, and explains how custom components can be registered. Understanding the registry helps you choose the right component for your use case and ensures that component values in your form schema are valid.
For details on how components receive their props and events at runtime, see the Schema Structure and Data Binding guides.
How Components Are Registered
Components are registered with a namespace and type, forming a key in the format namespace:type. The global registry is initialized at startup by scanning all card Vue files and registering them under the card namespace.
// Registration format
registry.register("card", {
type: "label",
name: "Label",
category: "card",
implementation: () => LabelComponent,
options: [],
supportsChildren: false,
});
Resolving Components
When a UINode specifies a component, the renderer resolves it through the registry:
- Full key:
"card:label" — matches directly against the namespace:type key.
- Alias:
"label" — the registry maintains an alias map from type name to full key, so short names also work.
Both of these are equivalent:
{ "component": "card:label" }
{ "component": "label" }
Using the full namespace:type format is recommended for clarity and to avoid ambiguity if multiple namespaces register components with the same type name.
ComponentDefinition Interface
Each registered component has the following metadata:
| Field | Type | Description |
|---|
type | string | The component type identifier (e.g., "label", "cardPanel") |
name | string | Human-readable display name |
category | string | One of "card", "option", "layout", "kendo", "custom" |
implementation | function | Factory function returning the Vue component |
options | any[] | Configuration options accepted by the component |
supportsChildren | boolean | Whether the component can contain child nodes |
defaults | Record<string, any> | Default prop values |
emits | Record<string, object> | Events the component emits, with payload descriptions |
slots | Record<string, object> | Named slots the component provides |
Available Card Components
All built-in card components are registered under the card namespace. They are automatically discovered from Vue files following the naming convention kodexa-form-card-*.vue.
Layout Cards
Layout cards organize and structure form content. They typically support children.
| Component | Type | Supports Children | Description |
|---|
| Card Group | cardGroup | Yes | Container for visually grouping related cards together. Renders children in a shared visual boundary. |
| Card Panel | cardPanel | Yes | Full-featured panel with title bar, tabs, exception handling, and collapsible content. The most commonly used container component. |
| Tabs | tabs | Yes | Presents child cards in a tabbed interface. Each child becomes a separate tab. |
| Horizontal Line | horizonalLine | No | Visual separator line for organizing content within a form. |
The horizontal line component type is horizonalLine (note the spelling). This matches the underlying Vue file name.
Display Cards
Display cards show data in read-only or summary formats.
| Component | Type | Supports Children | Description |
|---|
| Label | label | No | Displays static text or dynamic values. Commonly used for headings, field labels, and computed display values. |
| Single Taxon | singleTaxon | No | Displays a single taxonomy value with formatting appropriate to the taxon type. |
| Coming Soon | comingSoon | No | Placeholder component for features under development. |
Data Grid Cards
Grid cards display tabular data with sorting, filtering, and interaction capabilities.
| Component | Type | Supports Children | Description |
|---|
| Grid | grid | No | Standard data grid with sorting and filtering. Displays data from a configured source. |
| Data Store Grid | dataStoreGrid | No | Grid connected directly to a Kodexa data store. Supports pagination and server-side operations. |
| Taxon Grid | taxonGrid | No | Grid specialized for displaying taxonomy-structured data with columns derived from taxon paths. |
| Workspace Data Grid | workspaceDataGrid | No | Grid that displays data across workspaces, supporting cross-workspace queries. |
| Transposed Grid | transposedGrid | No | Grid with rows and columns swapped, useful for comparison views where attributes become rows. |
| Transposed Grid Rollup | transposedGridRollup | No | Transposed grid with hierarchical rollup calculations. Supports drag-and-drop reordering and aggregation. |
| Transposed Grid Aggregated Cell | transposedGridAggregatedCell | No | Specialized cell component for aggregated values within transposed grid rollups. |
| Transposed Grid Data Property Rollup | transposedGridDataPropertyRollup | No | Rollup component that aggregates based on data object properties rather than attribute values. |
Tree View Cards
Tree cards visualize hierarchical data structures.
| Component | Type | Supports Children | Description |
|---|
| Data Objects Tree | dataObjectsTree | No | Tree view of nested data objects, showing the parent-child hierarchy. |
| Workspace Data Tree View | workspaceDataTreeView | No | Tree view of the workspace data structure, including document families and their objects. |
Editor Cards
Editor cards provide interactive components for data modification.
| Component | Type | Supports Children | Description |
|---|
| Data Attribute Editor | dataAttributeEditor | No | Edit individual data attributes with type-appropriate input controls and validation. |
| Exceptions | exceptions | No | Display and manage data exceptions and errors associated with data objects. |
| Taxon Tabs | taxonTabs | No | Tabbed interface for managing taxonomy-level data, with tabs derived from taxon structure. |
Using Components in V2 Nodes
Reference any registered component by its type in the component field of a UINode:
{
"version": "2",
"nodes": [
{
"component": "card:cardPanel",
"props": {
"title": "Invoice Details",
"groupTaxon": "invoice",
"showHeader": true
},
"children": [
{
"component": "card:label",
"props": { "label": "Invoice Number" }
},
{
"component": "card:dataAttributeEditor",
"props": { "taxon": "invoice/invoiceNumber" }
},
{
"component": "card:dataAttributeEditor",
"props": { "taxon": "invoice/totalAmount" }
}
]
},
{
"component": "card:taxonGrid",
"props": {
"groupTaxon": "lineItem"
}
}
]
}
Checking Children Support
Only components with supportsChildren: true can contain child nodes. If you add children to a component that does not support them, the children will be ignored.
Containers that support children: cardPanel, cardGroup, tabs.
Layout Components
In addition to card components, V2 forms support layout through CSS classes and the class and style fields on UINode. The grid layout system from V1 (layout.x, layout.y, layout.w, layout.h) continues to work for card components that expect it.
For V2-specific layout, use CSS utility classes:
{
"component": "card:cardPanel",
"class": "mt-4 mb-2",
"style": { "maxWidth": "800px" },
"children": [ ... ]
}
Registering Custom Components
The component registry supports runtime registration of custom components. This allows extensions and plugins to add new component types that can be referenced in V2 form schemas.
Registration API
import { getGlobalRegistry } from "@/schema/registry";
const registry = getGlobalRegistry();
registry.register("custom", {
type: "myWidget",
name: "My Custom Widget",
category: "custom",
implementation: () => MyWidgetComponent,
options: [],
supportsChildren: false,
defaults: { color: "blue" },
emits: {
"value-changed": {
payload: "{ value: any, previous: any }",
description: "Fired when the widget value changes",
},
},
});
Using Custom Components
Once registered, custom components are referenced by their full key:
{
"component": "custom:myWidget",
"props": { "color": "red" },
"events": {
"value-changed": {
"type": "script",
"target": "kodexa.log.debug('Widget value changed')"
}
}
}
Custom Component Requirements
Custom components should:
- Accept props via Vue
defineProps: The renderer passes resolved props (from both props and bindings) via v-bind.
- Emit events via Vue
defineEmits: The renderer attaches handlers via v-on based on the events configuration.
- Use the default slot for children: If
supportsChildren is true, child nodes are rendered in the component’s default slot.
<script setup lang="ts">
defineProps<{
color?: string;
label?: string;
}>();
const emit = defineEmits<{
(e: "value-changed", payload: { value: any }): void;
}>();
</script>
<template>
<div :style="{ color }">
{{ label }}
<slot /> <!-- children render here -->
</div>
</template>
Common Patterns
{
"version": "2",
"nodes": [
{
"component": "card:label",
"props": { "label": "Document Overview" }
},
{
"component": "card:cardPanel",
"props": { "title": "Header", "groupTaxon": "invoice" },
"children": [
{ "component": "card:dataAttributeEditor", "props": { "taxon": "invoice/vendorName" } },
{ "component": "card:dataAttributeEditor", "props": { "taxon": "invoice/invoiceDate" } }
]
},
{
"component": "card:transposedGridRollup",
"props": { "groupTaxon": "lineItem" }
},
{
"component": "card:exceptions"
}
]
}
Querying the Registry Programmatically
const registry = getGlobalRegistry();
// Get all card components
const cards = registry.getByCategory("card");
// Check if a component exists
const def = registry.resolve("card:taxonGrid");
if (def) {
console.log(def.name, "supports children:", def.supportsChildren);
}
Next Steps