GraphInstance Expand and Collapse API
This example shows how to get a provider-scoped relation-graph instance with `RGHooks.useGraphInstance()`, load a small inline tree, and normalize the viewport after mount. It then demonstrates one focused control pattern: an external button resolves node `b` by id and toggles that branch with `expandNode()` or `collapseNode()`.
Use GraphInstance to Expand or Collapse a Target Node
What This Example Builds
This example builds a compact left-to-right tree demo whose real purpose is API control, not data storytelling. Users see a full-height page with an instructional header, a green callout, one action button, and a minimally styled graph canvas underneath.
The important interaction is the header button. It looks up node b through the provider-scoped graph instance and toggles that branch between expanded and collapsed states. Node clicks are also wired, but they only log the clicked label and do not change the graph.
The main point to watch is the end-to-end instance workflow: get the active graph instance from RGHooks.useGraphInstance(), load data, normalize the viewport, then drive a specific branch from ordinary surrounding UI.
How the Data Is Organized
The data is declared inline inside initializeGraph() as one RGJsonData object with rootId: 'a', a flat nodes array, and a flat lines array. The structure describes a small hierarchy with 16 nodes and 15 links, so the example stays focused on instance method usage instead of on remote loading or data transformation.
Before the graph is loaded, the code runs one preprocessing step over the line list: if a line does not already have an id, it assigns line-${index}. After that normalization pass, the dataset is sent directly to setJsonData().
In a real application, the same flat nodes-and-lines structure could represent an org branch, a dependency tree, a course outline, an approval chain, or any other hierarchy where external controls need to reveal or hide a known branch by id.
How relation-graph Is Used
index.tsx wraps the example in RGProvider, and MyGraph.tsx obtains the active graph instance with RGHooks.useGraphInstance(). A mount-only useEffect() calls initializeGraph(), which builds the inline dataset, normalizes missing line ids, then runs setJsonData(), moveToCenter(), and zoomToFit().
The graph uses layoutName: 'tree' with from: 'left', treeNodeGapH: 120, and treeNodeGapV: 10, so it reads as a horizontal tree. Nodes default to rectangular 100x30 blocks, links use RGLineShape.StandardCurve, link anchors use RGJunctionPoint.lr, the built-in expand holder is placed on the right edge, and reLayoutWhenExpandedOrCollapsed is enabled so branch toggles reorganize the tree automatically.
There are no custom node, line, canvas, or viewport slots, and there is no editing workflow. The local SCSS file only contains empty selector scaffolding, so the example stays close to relation-graph defaults. The only shared local dependency used in the visible UI is SimpleUIButton from the common DraggableWindow module; the draggable panel and screenshot helpers defined in that shared code are not mounted here.
Key Interactions
- Clicking the header button looks up node
band toggles it withcollapseNode(...)orexpandNode(...). - Because
reLayoutWhenExpandedOrCollapsedis enabled, the tree reflows after that programmatic branch change instead of keeping stale spacing. - Clicking a node triggers
onNodeClick, but the handler only logsnodeItem.text, so node inspection is secondary to the API lesson.
Key Code Fragments
This wrapper proves that the demo relies on provider context before it reads the graph instance from hooks.
const Demo = () => {
return (
<RGProvider>
<MyGraph />
</RGProvider>
);
};
This fragment shows the provider-scoped instance access and the horizontal tree layout configuration.
const MyGraph = () => {
const graphInstance = RGHooks.useGraphInstance();
const graphOptions: RGOptions = {
layout: {
layoutName: 'tree',
from: 'left',
treeNodeGapH: 120,
treeNodeGapV: 10
},
This options block proves that the example is tuned for a rectangular left-to-right tree that relayouts after expand-state changes.
defaultNodeShape: RGNodeShape.rect,
defaultNodeWidth: 100,
defaultNodeHeight: 30,
defaultLineShape: RGLineShape.StandardCurve,
defaultNodeBorderWidth: 1,
defaultJunctionPoint: RGJunctionPoint.lr,
reLayoutWhenExpandedOrCollapsed: true,
defaultExpandHolderPosition: 'right',
debug: false
This excerpt shows that the graph data is assembled inline as a flat tree before it is loaded.
const myJsonData: RGJsonData = {
rootId: 'a',
nodes: [
{ id: 'a', text: 'a' },
{ id: 'b', text: 'b' },
{ id: 'b1', text: 'b1' },
// ...
{ id: 'c3', text: 'c3' }
],
lines: [
This preprocessing step backfills missing line ids before setJsonData() runs.
myJsonData.lines.forEach((line, index) => {
if (!line.id) {
line.id = `line-${index}`;
}
});
This initialization sequence is the complete mount-time graph setup.
await graphInstance.setJsonData(myJsonData);
graphInstance.moveToCenter();
graphInstance.zoomToFit();
This handler is the core API demonstration: surrounding UI resolves one known node id and toggles that branch directly.
const callApi = () => {
const targetNodeId = 'b';
const targetNode = graphInstance.getNodeById(targetNodeId);
if (targetNode) {
if (targetNode.expanded === true) {
graphInstance.collapseNode(targetNode);
} else {
graphInstance.expandNode(targetNode);
}
}
};
This header fragment shows how the external button is presented as the main teaching surface above the graph.
<div className="px-4 py-2 bg-green-200 rounded mt-2 mb-2 flex gap-2">
<Info size={16} /> The following examples demonstrate the effect of expanding/collapsing a specific node by calling the API interface:
</div>
<SimpleUIButton onClick={callApi}>
Expanding / Collapsing Node "b"
</SimpleUIButton>
What Makes This Example Distinct
The comparison data places this example near customize-fullscreen-action, expand-gradually, expand-graph-step-by-step, and adv-hide-2-show, but its focus is narrower than all of them. It uses a similar provider-and-instance setup and a similarly generic tree scaffold, then concentrates almost all of its teaching value on one repeatable pattern: surrounding UI can resolve a known node id and control that branch through the graph instance.
Compared with customize-fullscreen-action and adv-hide-2-show, this example keeps the wrapper simple and uses post-load instance control as the main lesson instead of fullscreen targeting or delayed first visibility. Compared with expand-gradually, it does not teach startup collapse plus click-led disclosure. Compared with expand-graph-step-by-step, it avoids recursive playback and animation choreography in favor of the smallest deterministic control case.
That makes this example a stronger starting point when the real requirement is not “render a tree” but “connect one ordinary page control to one known graph branch.” The distinctive combination is hook-based instance access, inline flat tree data, defensive line-id normalization, immediate center-and-fit initialization, and an external button that repeatedly toggles node b in a plain left-to-right tree.
Where Else This Pattern Applies
This pattern transfers well to dashboards where a filter panel or summary card needs to reveal a known subtree, to onboarding flows where a help panel opens one branch of a concept map, and to org or dependency viewers where a surrounding control should focus attention on one predefined section without rebuilding the dataset.
It also works for tutorial pages and debugging tools that need to demonstrate one concrete graph operation in isolation. The reusable idea is simple: keep the graph instance inside provider scope, resolve the target node by id, and let ordinary page UI trigger instance methods instead of forcing every action to start inside the canvas.