Isolated Nodes
This example shows how to keep visually isolated nodes inside a relation-graph `circle` layout without drawing extra visible relationships. It starts from a small inline `RGJsonData` payload, derives a root from the first node, adds hidden helper edges with `opacity: 0`, and then loads, centers, and fits the graph on mount.
Keeping Isolated Nodes Visible in a Circle Layout
What This Example Builds
This example builds a full-height relation-graph viewer that arranges a sparse set of circular nodes into one orbit-like circle. Several nodes appear to have no visible relationships, but they still stay in the layout because the dataset is augmented with hidden structural edges before loading. Users can inspect the graph and click nodes or lines, although those clicks only write the clicked objects to the console.
How the Data Is Organized
The graph data is created inline inside initializeGraph() as one RGJsonData object with 19 nodes and 5 explicit lines. Before the data is loaded, the code derives rootId from the first node (a) and appends one extra root-to-node line for every other node with opacity: 0. In a real application, the same structure can represent people, devices, services, accounts, or records where some items have no visible relationship but still need stable placement inside one shared layout.
How relation-graph Is Used
index.tsx wraps the example in RGProvider, and MyGraph.tsx retrieves the provider-scoped instance with RGHooks.useGraphInstance(). The graph options enable relation-graph’s built-in circle layout, use border junction points, render nodes as 60 by 60 circles, and keep the default line width at 2. A mount-time useEffect() runs the initialization sequence: assemble the data, inject hidden helper edges, call setJsonData(), then moveToCenter() and zoomToFit().
The example does not use custom slots, viewport tools, editor features, or extra graph subcomponents beyond RGProvider and RelationGraph. The reviewed SCSS file is only a shell of empty selectors, so the visible result is essentially relation-graph defaults plus the chosen layout and the inline wrapper height.
Key Interactions
- The graph loads automatically when the component mounts, then immediately centers and fits itself to the viewport.
- Clicking a node triggers
onNodeClick, but the handler only logs the node object. - Clicking a line triggers
onLineClick, but the handler only logs the line object. - There is no toolbar, expand/collapse flow, edit mode, or selection workflow in this example.
Key Code Fragments
This options block shows that the example relies on relation-graph’s built-in circle layout and circular node defaults.
const graphOptions: RGOptions = {
debug: false,
defaultJunctionPoint: RGJunctionPoint.border,
defaultNodeShape: RGNodeShape.circle,
defaultNodeWidth: 60,
defaultNodeHeight: 60,
defaultLineWidth: 2,
layout: {
layoutName: 'circle'
}
};
This preprocessing pass is the core workaround: it derives a root and appends hidden helper lines before the graph is loaded.
const rootId = myJsonData.nodes[0].id;
myJsonData.rootId = rootId;
let lineIndex = myJsonData.lines.length + 1;
myJsonData.nodes.forEach(n => {
if (n.id !== rootId) {
myJsonData.lines.push({
id: `l${lineIndex++}`,
from: rootId,
to: n.id,
opacity: 0
});
}
});
This mount-time sequence proves that the augmented dataset is loaded and framed automatically instead of waiting for a manual action.
useEffect(() => {
initializeGraph();
}, []);
// ...
await graphInstance.setJsonData(myJsonData);
graphInstance.moveToCenter();
graphInstance.zoomToFit();
This handler pair shows that user interaction is limited to inspection-oriented logging.
const onNodeClick = (nodeObject: RGNode, $event: RGUserEvent) => {
console.log('onNodeClick:', nodeObject);
};
const onLineClick = (lineObject: RGLine, linkObject: RGLink, $event: RGUserEvent) => {
console.log('onLineClick:', lineObject);
};
What Makes This Example Distinct
According to the prepared comparison data, this example is a plain baseline reference for one specific workaround: keep isolated-looking nodes inside a circle layout by manufacturing an invisible connected backbone before setJsonData(). That combination of inline static data, load-time augmentation, log-only click handlers, and a mostly default full-height canvas is the part that is rare, not the use of RGProvider or the standard load-center-fit API sequence by itself.
Compared with show-single-nodes3, this version stays intentionally plain and does not turn visible line styling into part of the lesson. Compared with show-single-nodes2, it uses the same hidden-helper idea but keeps the placement strictly circle-based instead of switching to a force layout. Compared with multi-group-2, it does not render disconnected groups as-is; it rewrites the payload so nodes can still look isolated while participating in one chosen layout.
Where Else This Pattern Applies
This pattern transfers well to import-review and monitoring screens where some entities arrive without visible relationships but still need to stay on the canvas: unassigned employees in an org dataset, services without declared dependencies, partially matched customer records, or knowledge-graph entities that are waiting for links to be confirmed. It is also useful when a team wants the visual message of “these items are currently isolated” without giving up the stability of one built-in layout algorithm.