Skip to content

Creating a layout widget

A layout widget is a container. It receives a children array from the form definition and is responsible for rendering them. The example we’ll walk through is productCard — a card container with a title header that wraps its children inside a styled card.

import { gui } from '@golemui/gui-shared';
gui.layouts.custom('productCard', [
// child widgets go here
], { title: 'Product Card Name' });
  • useLayoutWidget (React) and LayoutWidgetAdapter (Angular / Lit) give you the children array, already filtered by any include/exclude rules.
  • You must render each child using the framework’s widget renderer: WidgetRenderer (React), the guiWidget directive (Angular), or the <gui-widget> element (Lit).
  • The templateData object contains your custom props (like title) merged with calculated properties from the form engine (size, lang, deps).
ProductCard.tsx
import * as Core from '@golemui/core';
import { useLayoutWidget, WidgetRenderer } from '@golemui/react';
interface ProductCardProps {
title: string;
}
export function ProductCard(widgetInstance: Core.WithWidget) {
const widget = widgetInstance.widget as Core.LayoutWidget;
const { uid, children, templateData } =
useLayoutWidget<ProductCardProps>(widget);
return (
<div className="product-card" style={{ flex: templateData.size }}>
<div className="product-card__widget" id={uid}>
<h2 className="product-card__title">{templateData.title}</h2>
<div className="product-card__content">
{children.map((child) => {
const w = child as Core.NonFunctionWidget<string>;
return <WidgetRenderer key={w.uid} widget={w} />;
})}
</div>
</div>
</div>
);
}

useLayoutWidget returns:

  • uid — unique identifier for the widget DOM node
  • children — the resolved child widgets, filtered by visibility rules
  • templateData — your custom props (title) plus engine-managed properties (size, lang, deps)
  • onChange — a callback to emit change events with an optional detail payload

Here’s the Product Card layout rendering its child widgets: