JavaScript is required

Node Data Model (JsonNode / RGNode)

Nodes are the most basic data unit in relation-graph. A node is both a business entity and the base object used for layout, rendering, hit testing, and interaction.

In real projects you will usually work with two node object shapes:

  • JsonNode: the input data object you pass into the graph. It appears in nodes, children, addNode, addNodes, and setJsonData.
  • RGNode: the runtime node object generated by relation-graph. It appears in getNodeById, getNodes, event callbacks, slot props, and editor components.

JsonNode is the input format; RGNode is the runtime format. Do not persist a full runtime object as business data. For export or persistence, use getGraphJsonData() or transRGNodeToJsonObject().

1. Minimal Node

A minimal node only needs id:

const node = {
  id: 'user-1'
};

In real projects you normally also set text:

const node = {
  id: 'user-1',
  text: 'John Smith'
};

Rules:

  • id must be unique and stable. The graph uses it to build node indexes, line endpoints, expand/collapse relationships, and update targets.
  • text is the displayed node text. relation-graph uses text, not label.
  • The current source code keeps compatibility with older data: when a new node has no text but has label, label is used as text and a warning is printed; when neither exists, id may be used as text. New code should not rely on this compatibility behavior.

2. JsonNode Fields

Identity And Business Fields

Field Type Default Description
id string Required Unique node id. Line from/to, update APIs, and query APIs all depend on it.
text string '', or compatible fallback to label/id Node text. The default node template displays it; custom node slots also usually read it as the title.
type string '' Business type. It can be used to dispatch slot templates and affects node type class names for CSS.
data Record<string, any> {} Business extension data. Put business attributes here instead of mixing them into relation-graph structural fields.
targetType string RGInnerConnectTargetType.Node Type marker when the node is used as a connect target. Normal nodes usually do not need this; it matters mainly for FakeLine or editor extensions.

Visibility, Expansion, And Interaction Fields

Field Type Default Description
expanded boolean true Whether this node is expanded in tree-like relationships. When collapsed, descendant nodes are hidden during visibility calculation.
hidden boolean false Explicitly hides this node. A hidden node is not rendered normally and affects related line visibility.
selected boolean false The node’s selected/multi-selected state, often used by editors for batch operations. It is not the same as the single checked state stored by checkedNodeId.
disablePointEvent boolean Follows options.disableNodePointEvent when unset Disables mouse/touch hit testing for this node. Useful for decorative nodes or click-through behavior.
disableDrag boolean false Disables dragging for this node. Actual draggability is also affected by global options.disableDragNode.
expandHolderPosition 'hide' | 'left' | 'top' | 'right' | 'bottom' | string Follows options.defaultExpandHolderPosition when unset Per-node expand/collapse button position. Use hide to hide the button for this node.
alwaysRender boolean Unset Rendering hint in performance mode. The source code treats it specially during visible-item calculation so the node is more likely to remain rendered. Normal business nodes usually do not need it.

Difference between expanded and hidden:

  • hidden hides the node itself.
  • expanded: false collapses a tree relationship and makes descendants invisible.
  • If you directly batch-modify hidden or expanded, call updateNodesVisibleProperty() when needed so runtime visibility is recalculated.

Shape And Appearance Fields

Field Type Default Description
nodeShape RGNodeShape options.defaultNodeShape, default RGNodeShape.rect Node geometry. It affects the default node appearance, line-to-node intersection calculation, and MiniView/EasyView drawing.
color string options.defaultNodeColor, default #ffffff Node background color. Use a valid CSS color value.
borderColor string options.defaultNodeBorderColor, default #666666 Node border color.
borderWidth number options.defaultNodeBorderWidth, default 1 Node border width, interpreted as pixels.
borderRadius number options.defaultNodeBorderRadius, default 4 Node corner radius, mainly for rectangular nodes.
fontColor string CSS default variable Default node text color. When using a fully custom node slot, this only works if your slot uses these variables/fields.
fontSize number CSS default variable Default node font size.
opacity number 1 Node opacity. Recommended range is 0 to 1.
className string '' Extra class added to the node DOM. Useful for theme-level style overrides.
zIndex number 0 Node stacking order. Controls overlap between nodes.

RGNodeShape values:

Enum Value Description
RGNodeShape.circle 0 Circular node. Line intersections are calculated against a circle/ellipse boundary; MiniView draws it as a circle.
RGNodeShape.rect 1 Rectangular node. Default value. Line intersections are calculated against a rectangle boundary or a specified side.

Size And Coordinate Fields

Field Type Default Description
x number 0 X coordinate of the node’s top-left corner in canvas coordinates. Automatic layout rewrites it.
y number 0 Y coordinate of the node’s top-left corner in canvas coordinates. Automatic layout rewrites it.
width number options.defaultNodeWidth or DOM measurement Logical node width. Setting it also affects the initial el_W.
height number options.defaultNodeHeight or DOM measurement Logical node height. Setting it also affects the initial el_H.
el_W number Runtime measurement Actual rendered node width. It can be provided as an initial measurement, but is usually updated from the DOM by the graph.
el_H number Runtime measurement Actual rendered node height. It can be provided as an initial measurement, but is usually updated from the DOM by the graph.
fixed boolean false Fixes the node position. Layout processing for additional groups skips fixed nodes; force layouts often use it to keep a node from moving automatically.
force_weight number Unset Node weight/mass-like value in force layouts. Higher values usually make the node “heavier” in the force simulation; exact behavior depends on the layout implementation.

Coordinate and size notes:

  • x/y are canvas coordinates, not page coordinates.
  • width/height express the size you want the node to have.
  • el_W/el_H are runtime measurements. Many layouts and line calculations depend on them.
  • If you use complex custom node slots without setting width/height, layout usually needs to wait until the first DOM measurement is complete.

Tree Input Field

Field Type Default Description
children JsonNode[] None Shortcut for tree-shaped input data. During import, it is flattened into nodes and lines.

children is only for the input stage:

const data = {
  rootId: 'root',
  nodes: [
    {
      id: 'root',
      text: 'Root',
      children: [
        { id: 'child-1', text: 'Child 1' },
        { id: 'child-2', text: 'Child 2' }
      ]
    }
  ],
  lines: []
};

await graphInstance.setJsonData(data);

After import, runtime data is managed through flat nodes, lines, and internal lot structures. Do not modify node.children at runtime and expect the graph to automatically add or remove nodes.

3. RGNode Runtime Fields

RGNode inherits most JsonNode fields and adds runtime-calculated information.

Field Type Description
type string Always exists at runtime. Empty string when unset.
x / y number Always exists at runtime. Defaults to 0 when unset.
nodeShape RGNodeShape Always exists at runtime, resolved from the node itself or defaultNodeShape.
data Record<string, any> Always exists at runtime. Defaults to {}.
lot object Internal layout/tree relationship structure. Contains parent/child nodes, depth, order, strength, and other layout fields. Do not persist it as business data.
rgChildrenSize number Runtime count related to child size/expandability.
rgShouldRender boolean Whether the node should be rendered after performance mode or viewport culling.
rgCalcedVisibility boolean Calculated visibility after combining hidden, parent collapse, and runtime rules.

Typical read:

const node = graphInstance.getNodeById('user-1');

if (node?.rgCalcedVisibility) {
  console.log(node.x, node.y, node.el_W, node.el_H);
}

Fields you should avoid relying on directly:

  • lot: internal layout relationship field. Its shape may change between versions.
  • rgShouldRender: result of a performance rendering strategy, not business visibility.
  • el_W/el_H: useful for reading layout/helper-line information, but usually not worth persisting.

4. Create, Query, Update, Delete Nodes

Create Nodes

graphInstance.addNode({
  id: 'n1',
  text: 'Node 1'
});

graphInstance.addNodes([
  { id: 'n2', text: 'Node 2' },
  { id: 'n3', text: 'Node 3', x: 200, y: 80 }
]);

addNodes skips nodes whose id already exists. It does not overwrite an existing node with the same id. Use updateNode to modify an existing node.

Query Nodes

const node = graphInstance.getNodeById('n1');
const nodes = graphInstance.getNodes();
const checkedNode = graphInstance.getCheckedNode();
const selectedNodes = graphInstance.getSelectedNodes();

Update Nodes

graphInstance.updateNode('n1', {
  text: 'Node 1 (updated)',
  color: '#dbeafe',
  borderColor: '#2563eb'
});

graphInstance.updateNodePosition('n1', 320, 160);

graphInstance.updateNodeData('n1', {
  owner: 'team-a',
  status: 'running'
});

Update rules:

  • updateNode(id, partial) shallow-merges fields.
  • To merge business data only, prefer updateNodeData.
  • To change position, prefer updateNodePosition; while a force layout is running, it also syncs the layout’s internal cache.

Delete Nodes

graphInstance.removeNodeById('n1');

graphInstance.removeNodesByIds(['n2', 'n3']);

const node = graphInstance.getNodeById('n4');
if (node) {
  graphInstance.removeNode(node);
}

Deleting a node is handled by the data provider together with related runtime data. In business applications, confirm whether associated lines should also be removed according to your own rules before deleting.

5. Recommended Data Style

const nodes = [
  {
    id: 'service-api',
    text: 'API Service',
    type: 'service',
    nodeShape: RGNodeShape.rect,
    color: '#eff6ff',
    borderColor: '#2563eb',
    borderWidth: 1,
    borderRadius: 8,
    width: 160,
    height: 56,
    data: {
      owner: 'Platform Team',
      level: 'Core System'
    }
  },
  {
    id: 'cache',
    text: 'Redis',
    type: 'middleware',
    fixed: true,
    x: 360,
    y: 120,
    data: {
      cluster: 'cache-prod'
    }
  }
];

Recommended principles:

  • Use id/text/type/data to describe the business entity.
  • Use color/borderColor/borderWidth/borderRadius/nodeShape for core visual semantics.
  • Use className for theme extension; do not put every visual meaning only in CSS.
  • Use width/height to stabilize layout, especially with custom node slots.
  • Use fixed to distinguish manually positioned nodes from automatically laid-out nodes.

6. FAQ

Why Did My Node Position Change?

Calling setJsonData(), doLayout(), or appendJsonData(..., true) causes the layout engine to recalculate node positions. If you need fully manual placement, use layoutName: 'fixed' or avoid automatic relayout after updates.

Why Did Lines Disappear When A Node Was Hidden?

Normal line visibility references the calculated visibility of its start and end nodes. If either endpoint is invisible, the related RGLink usually does not render.

Why Does My Custom Node Slot Not Match MiniView?

MiniView/EasyView reads node data fields such as nodeShape, color, borderColor, and borderWidth. If you only set background and border in slot CSS, MiniView cannot infer that visual meaning.

What Is The Difference Between selected And Checked?

  • selected is a field on the node itself. It is suitable for multi-select and batch editing.
  • Checked state is managed by options.checkedNodeId / checkedItem, and usually represents the current focused node.

7. Next