Getting StartedInstallation and setup guides 6
FormInput and selection components 27
FlowWorkflow graph and execution surfaces 4
LayoutStructural layout components 9
NavigationMenu surfaces and hierarchical actions 7
OverlayModal and floating layer surfaces 3
FeedbackStatus, empty, progress, and loading placeholder patterns 6
UtilityGeneral-purpose interface utilities 7

Node Properties API

Import TngFlowNodePropertiesComponent, the TngFlowNodePropertiesDataTemplateDirective, and related event types from @tailng-ui/flow/execution. The component is controlled: it displays the selected node and emits change requests for the application to apply.

Properties inputs

Provide either node directly or definition plus inspectedNodeId. A direct node value takes precedence, which is useful when the surrounding app already resolves selection.

NameTypeDefaultDescription
definitionTngFlowDefinition<TData> | nullnullWorkflow definition used to resolve the inspected node by id.
nodeTngFlowNode<TData> | nullnullExplicit selected node. When present, this overrides definition lookup.
inspectedNodeIdstring | nullnullNode id to inspect when the component receives a full definition.
readonlybooleanfalse Disables editable controls and prevents built-in fields or custom templates from emitting change requests.
showDatabooleantrueShows the Data section with either the JSON preview or custom data template.
showPortsbooleantrueShows the Ports section with input and output port metadata.

Definition lookup

html
<tng-flow-node-properties
  [definition]="definition()"
  [inspectedNodeId]="selectedNodeId()"
  [readonly]="isLocked()"
  (nodeChangeRequested)="applyNodeChanges($event)"
/>

Direct node

html
<tng-flow-node-properties
  [node]="selectedNode()"
  [showData]="false"
  [showPorts]="true"
  (nodeChangeRequested)="applyNodeChanges($event)"
/>

Properties outputs

The component never mutates the supplied node or definition. Listen for nodeChangeRequested, validate the request if needed, then merge the partial changes into application state.

NameTypeDescription
nodeChangeRequestedTngFlowNodePropertyChangeRequest<TData> Emitted for built-in name, description, disabled, and locked edits, and for custom data template requests.
Payload fieldTypeDescription
nodeTngFlowNode<TData>The node that was displayed when the request was created.
nodeIdstringStable id for matching the request back to the definition.
changesTngFlowNodePropertyChanges<TData> Partial changes for name, description, disabled, locked, or data.
source'field' | 'data-template' Identifies whether the request came from built-in fields or a projected template.

Controlled update handler

ts
import type { TngFlowNodePropertyChangeRequest } from '@tailng-ui/flow/execution';

protected applyNodeChanges(
  request: TngFlowNodePropertyChangeRequest<AgentNodeData>,
): void {
  this.definition.update((definition) => ({
    ...definition,
    nodes: definition.nodes.map((node) =>
      node.id === request.nodeId ? { ...node, ...request.changes } : node,
    ),
  }));
}

Data template

Project ng-template[tngFlowNodePropertiesData] when a product needs a typed data editor or a domain-specific readonly summary. The template replaces only the Data section body; the built-in header, base fields, and port list remain available.

Context valueTypeDescription
$implicit, dataTData | undefinedThe selected node data.
nodeTngFlowNode<TData>The selected node record.
readonlybooleanUse this to disable custom controls consistently with the built-in fields.
requestDataChange(data: TData | undefined) => voidRequests a data-only node update.
requestNodeChange(changes: TngFlowNodePropertyChanges<TData>) => voidRequests any supported node property update from the custom template.

Custom data template

html
<tng-flow-node-properties
  [definition]="definition()"
  [inspectedNodeId]="selectedNodeId()"
  (nodeChangeRequested)="applyNodeChanges($event)"
>
  <ng-template
    tngFlowNodePropertiesData
    let-data
    let-node="node"
    let-readonly="readonly"
    let-requestDataChange="requestDataChange"
    let-requestNodeChange="requestNodeChange"
  >
    <label>
      Owner
      <input
        [value]="data?.owner ?? ''"
        [readOnly]="readonly"
        (input)="requestDataChange({ owner: $any($event.target).value })"
      />
    </label>

    <button
      type="button"
      [disabled]="readonly"
      (click)="requestNodeChange({ description: node.name + ' owner reviewed' })"
    >
      Mark reviewed
    </button>
  </ng-template>
</tng-flow-node-properties>