A2uiSurfaceComponent
Angular component that renders a single A2UI surface. It converts the surface's component map and data model into a json-render Spec, then delegates rendering to RenderSpecComponent.
Import:
Selector: a2ui-surface
#Inputs
| Input | Type | Required | Description |
|---|---|---|---|
surface | A2uiSurface | No* | The surface to render (legacy input shape) |
state | A2uiSurfaceState | No* | Chat-side surface state driving progressive rendering. Preferred over surface; takes priority when both are set |
catalog | A2uiViews | ViewRegistry | Yes | Component registry used to resolve A2UI type names to Angular components |
handlers | Record<string, (params) => unknown | Promise<unknown>> | No | Consumer A2UI action handlers for a2ui:localAction. Merged with the built-in a2ui:event / a2ui:localAction handlers; consumer handlers take priority |
surfaceFallback | Type<unknown> | undefined | No | Component mounted while no root component has arrived yet (instead of rendering nothing) |
surface and state are both optional individually, but the component needs one of them to render. state is the preferred progressive-rendering path; surface is the legacy shape.
#Outputs
| Output | Type | Description |
|---|---|---|
events | RenderEvent | Emits render events from the underlying RenderSpecComponent -- handler execution, state changes, and lifecycle signals |
action | A2uiActionMessage | Emits an agent-bound action message when an A2UI event action fires. Forward it to your agent (e.g. agent.submit) to resume the agent loop |
The events output forwards all RenderEvent emissions from the render engine. This includes events triggered by the default A2UI handlers (a2ui:event and a2ui:localAction) as well as any state change or lifecycle events. The action output is the agent-bound path: when a surface's event action fires, the component builds an A2uiActionMessage and emits it here so you can send it back to the agent.
#How It Works
A2uiSurfaceComponent bridges the A2UI surface model to the json-render engine in three steps:
1. Convert surface to Spec (surfaceToSpec)
The internal surface-to-spec conversion walks the flat component map and produces a json-render Spec. It uses a component with id: 'root' when present; otherwise it uses the first component in the map as the render root. Empty component maps render nothing.
2. Resolve dynamic values
Before the spec is emitted, each component prop is evaluated against the surface's data model. A prop can be:
- A literal value — passed through as-is
- A path reference
{ path: '/some/pointer' }— resolved via JSON Pointer againstdataModel
3. Map actions to on bindings
The internal conversion maps each component's A2UI action prop into a render-spec on binding on the corresponding element. Actions map to the a2ui:event handler, which builds an A2uiActionMessage for the (action) output.
4. Expand template children
When a component's children field is an A2uiChildTemplate ({ template: { componentId, dataBinding } }), the surface component expands it over the array at the dataBinding JSON Pointer in the data model. Each array item gets its own cloned element with props resolved in that item's scope.
5. Render via RenderSpecComponent
The final Spec is passed to RenderSpecComponent along with the ViewRegistry (converted to an Angular registry via toRenderRegistry). Rendering is fully reactive — when the surface signal updates, the spec recomputes and only affected elements re-render.
#Usage Outside ChatComponent
A2uiSurfaceComponent is used internally by ChatComponent, but you can also use it directly to embed a surface in any Angular template.
A2uiSurfaceComponent prefers a component with id: 'root' when one exists. If the surface has components but no root, it renders from the first component ID. Empty component maps render nothing.
#Wiring handlers and actions
The example above renders a surface but ignores interaction. To run client-owned behavior and forward agent-bound events, pass [handlers] and bind (action) / (events). Consumer handlers run for a2ui:localAction; the (action) output carries the agent-bound A2uiActionMessage.
#Internal conversion
A2uiSurfaceComponent handles surface-to-spec conversion internally when it receives a legacy surface input. That conversion returns no rendered output for an empty component map. Otherwise it produces a complete json-render Spec, preferring a root component when present and falling back to the first component ID.
The conversion helper is not part of the public @threadplane/chat API. Use A2uiSurfaceComponent or createA2uiSurfaceStore() for supported integration points.