Display More Nodes Button
Front-Loaded Node Display with Show All - Pre-load all data but show limited nodes initially, reveal all on demand
Front-Loaded Node Display with Show All Option
Functional Overview
This example demonstrates a “show all” pattern for displaying large numbers of child nodes. Instead of lazy loading with pagination, it pre-loads all data but initially hides nodes beyond a default visible count (3 nodes per category). Users can click a “Show More” button to reveal all hidden nodes at once. This approach provides fast access to full dataset while maintaining a clean initial view.
Implementation of Key Features
Initial Data Loading with Partial Visibility
The appendTypeData function loads all nodes but marks most as hidden:
const appendTypeData = async (myType: string) => {
const typeNode = graphInstance.getNodes().find(n => n.data.myType === myType);
const defaultVisibleCount = 3;
const allItems = await loadMockCompanys(myType);
const total = allItems.length;
const thisTypeJsonData: RGJsonData = { nodes: [], lines: [] };
for (const entItem of allItems) {
const companyNode: JsonNode = {
id: entItem.companyId,
text: entItem.companyName,
data: { ownerType: myType }
};
// Hide nodes beyond the default visible count
if (thisTypeJsonData.nodes.length > defaultVisibleCount) {
companyNode.hidden = true;
}
thisTypeJsonData.nodes.push(companyNode);
thisTypeJsonData.lines.push({ from: typeNodeId, to: companyNode.id });
}
updateLoadMoreButtonNode(typeNodeId, myType, defaultVisibleCount - 1, total, thisTypeJsonData);
// Position new nodes at parent location for smooth animation
thisTypeJsonData.nodes.forEach((n: JsonNode) => {
n.x = typeNode.x;
n.y = typeNode.y;
});
graphInstance.addNodes(thisTypeJsonData.nodes);
graphInstance.addLines(thisTypeJsonData.lines);
};
Key aspects:
- All data pre-loaded: Fetches complete dataset upfront
- Selective visibility: Only first 3 nodes displayed by default
- Hidden property: Uses
node.hidden = trueto conceal excess nodes - Batch addition: All nodes added to graph at once for efficiency
Show All Functionality
The showAllNodes function reveals all hidden nodes for a category:
const showAllNodes = async(buttonNode: RGNode) => {
const myType = buttonNode.data.loadType;
const typeNodes = graphInstance.getNodes().filter(n => n.data.ownerType === myType);
// Unhide all nodes of this type
typeNodes.forEach(n => {
graphInstance.updateNode(n.id, { hidden: false });
});
// Remove the "Show More" button
graphInstance.removeNodeById(buttonNode.id);
await graphInstance.doLayout();
};
Key aspects:
- Filter by type: Retrieves only nodes matching the category type
- Batch update: Updates visibility for all related nodes at once
- Button removal: Deletes the “Show More” button after revealing nodes
- Layout refresh: Re-calculates positions after showing all nodes
Show More Button Management
The updateLoadMoreButtonNode function adds a button showing remaining count:
const updateLoadMoreButtonNode = (
typeNodeId: string,
myType: string,
fromIndex: number,
total: number,
currentPageGraphJsonData: RGJsonData
) => {
const loadNextPageButtonNodeId = `${myType}-next-button`;
graphInstance.removeNodeById(loadNextPageButtonNodeId);
const remainingItemCount = total - fromIndex + 1;
if (remainingItemCount > 0) {
const loadNextPageButtonNode = {
id: loadNextPageButtonNodeId,
text: `Show More(${remainingItemCount})`,
data: { myType: 'more-btn', loadType: myType, fromIndex: (fromIndex + 1) }
};
currentPageGraphJsonData.nodes.push(loadNextPageButtonNode);
currentPageGraphJsonData.lines.push({
from: typeNodeId,
to: loadNextPageButtonNode.id
});
}
};
Custom Node Slot with Click Handler
The NodeSlot component handles the “Show More” button click:
const NodeSlot: React.FC<RGNodeSlotProps & {showAllNodes: (n: RGNode) => void|Promise<void>}> = ({ node, showAllNodes }) => {
const myType = node.data.myType;
const buttonTypes = ['investment-button', 'shareholder-button', 'historical-investment-button', 'historical-shareholder-button'];
return (
<>
{buttonTypes.includes(myType) && (
<div className="my-node my-button-node">{node.text}</div>
)}
{myType === 'root' && (
<div className="my-node my-root">{node.text}</div>
)}
{myType === 'more-btn' && (
<div className="my-node more-btn px-2" onClick={() => {showAllNodes(node)}}>
{node.text}
</div>
)}
{!myType && (
<div className="my-node">{node.text}</div>
)}
</>
);
};
Initialization with Multiple Categories
The graph initializes with four category nodes, each with pre-loaded hidden children:
const initializeGraph = async () => {
const myJsonData: RGJsonData = {
rootId: 'root',
nodes: [
{ id: 'root', text: 'Tian Technology Co., Ltd.', expandHolderPosition: 'hide', data: { myType: 'root' } },
{ id: 'root-invs', text: 'Investment', disablePointEvent: true, data: { myType: 'investment-button', childrenLoaded: false } },
{ id: 'root-history-invs', text: 'Historical Investment', data: { myType: 'historical-investment-button', childrenLoaded: false } },
{ id: 'root-sh', text: 'Share Holder', disablePointEvent: true, data: { myType: 'shareholder-button', childrenLoaded: false } },
{ id: 'root-history-shareholder', text: 'Historical Share Holder', data: { myType: 'historical-shareholder-button', childrenLoaded: false } }
],
lines: [
{ from: 'root', to: 'root-invs', showEndArrow: false },
{ from: 'root', to: 'root-history-invs', showEndArrow: false },
{ from: 'root', to: 'root-sh', showEndArrow: false },
{ from: 'root', to: 'root-history-shareholder', showEndArrow: false }
]
};
graphInstance.loading();
await graphInstance.setJsonData(myJsonData);
// Pre-load all categories with partial visibility
await appendTypeData('investment-button');
await appendTypeData('shareholder-button');
await appendTypeData('historical-investment-button');
await appendTypeData('historical-shareholder-button');
await graphInstance.sleep(400);
await graphInstance.doLayout();
graphInstance.clearLoading();
graphInstance.moveToCenter();
graphInstance.zoomToFit();
};
Tree Layout Configuration
const graphOptions: RGOptions = {
defaultExpandHolderPosition: 'right',
defaultNodeShape: RGNodeShape.rect,
defaultNodeBorderWidth: 0,
defaultLineShape: RGLineShape.StandardOrthogonal,
defaultPolyLineRadius: 5,
defaultJunctionPoint: RGJunctionPoint.lr,
reLayoutWhenExpandedOrCollapsed: true,
layout: {
layoutName: 'tree',
from: 'left',
treeNodeGapH: 100,
treeNodeGapV: 10,
alignItemsX: 'start',
alignParentItemsX: 'end',
}
};
Creative Use Cases
Corporate Structure Visualization: Display all subsidiaries of a conglomerate but show only key divisions initially. Allow executives to expand to see all sub-units when needed for detailed analysis.
Product Catalog Browsing: Show top 3 products in each category, hiding the rest. Shoppers can click “Show More” to reveal full product line in categories they’re interested in.
Organization Chart Explorer: Render company hierarchy with direct reports limited to 3. Users can reveal all team members within a department when they need complete visibility.
Network Dependency Map: Visualize system dependencies with only critical dependencies shown initially. Developers can expand to see all connections when troubleshooting complex systems.
File System Browser: Display folder contents with first 3 files visible. Users can reveal all files in a directory when searching for specific items without navigating away.