[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:en:graph-instance-expand-collapse-api":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# Use GraphInstance to Expand or Collapse a Target Node\n\n## What This Example Builds\n\nThis 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.\n\nThe 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.\n\nThe 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.\n\n## How the Data Is Organized\n\nThe 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.\n\nBefore 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()`.\n\nIn 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.\n\n## How relation-graph Is Used\n\n`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()`.\n\nThe 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.\n\nThere 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.\n\n## Key Interactions\n\n- Clicking the header button looks up node `b` and toggles it with `collapseNode(...)` or `expandNode(...)`.\n- Because `reLayoutWhenExpandedOrCollapsed` is enabled, the tree reflows after that programmatic branch change instead of keeping stale spacing.\n- Clicking a node triggers `onNodeClick`, but the handler only logs `nodeItem.text`, so node inspection is secondary to the API lesson.\n\n## Key Code Fragments\n\nThis wrapper proves that the demo relies on provider context before it reads the graph instance from hooks.\n\n```tsx\nconst Demo = () => {\n    return (\n        \u003CRGProvider>\n            \u003CMyGraph />\n        \u003C/RGProvider>\n    );\n};\n```\n\nThis fragment shows the provider-scoped instance access and the horizontal tree layout configuration.\n\n```tsx\nconst MyGraph = () => {\n    const graphInstance = RGHooks.useGraphInstance();\n\n    const graphOptions: RGOptions = {\n        layout: {\n            layoutName: 'tree',\n            from: 'left',\n            treeNodeGapH: 120,\n            treeNodeGapV: 10\n        },\n```\n\nThis options block proves that the example is tuned for a rectangular left-to-right tree that relayouts after expand-state changes.\n\n```tsx\n        defaultNodeShape: RGNodeShape.rect,\n        defaultNodeWidth: 100,\n        defaultNodeHeight: 30,\n        defaultLineShape: RGLineShape.StandardCurve,\n        defaultNodeBorderWidth: 1,\n        defaultJunctionPoint: RGJunctionPoint.lr,\n        reLayoutWhenExpandedOrCollapsed: true,\n        defaultExpandHolderPosition: 'right',\n        debug: false\n```\n\nThis excerpt shows that the graph data is assembled inline as a flat tree before it is loaded.\n\n```tsx\nconst myJsonData: RGJsonData = {\n    rootId: 'a',\n    nodes: [\n        { id: 'a', text: 'a' },\n        { id: 'b', text: 'b' },\n        { id: 'b1', text: 'b1' },\n        // ...\n        { id: 'c3', text: 'c3' }\n    ],\n    lines: [\n```\n\nThis preprocessing step backfills missing line ids before `setJsonData()` runs.\n\n```tsx\nmyJsonData.lines.forEach((line, index) => {\n    if (!line.id) {\n        line.id = `line-${index}`;\n    }\n});\n```\n\nThis initialization sequence is the complete mount-time graph setup.\n\n```tsx\nawait graphInstance.setJsonData(myJsonData);\ngraphInstance.moveToCenter();\ngraphInstance.zoomToFit();\n```\n\nThis handler is the core API demonstration: surrounding UI resolves one known node id and toggles that branch directly.\n\n```tsx\nconst callApi = () => {\n    const targetNodeId = 'b';\n    const targetNode = graphInstance.getNodeById(targetNodeId);\n    if (targetNode) {\n        if (targetNode.expanded === true) {\n            graphInstance.collapseNode(targetNode);\n        } else {\n            graphInstance.expandNode(targetNode);\n        }\n    }\n};\n```\n\nThis header fragment shows how the external button is presented as the main teaching surface above the graph.\n\n```tsx\n\u003Cdiv className=\"px-4 py-2 bg-green-200 rounded mt-2 mb-2 flex gap-2\">\n    \u003CInfo size={16} /> The following examples demonstrate the effect of expanding/collapsing a specific node by calling the API interface:\n\u003C/div>\n\u003CSimpleUIButton onClick={callApi}>\n    Expanding / Collapsing Node \"b\"\n\u003C/SimpleUIButton>\n```\n\n## What Makes This Example Distinct\n\nThe 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.\n\nCompared 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.\n\nThat 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.\n\n## Where Else This Pattern Applies\n\nThis 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.\n\nIt 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.\n",false,500,1782615436561]