JavaScript is required

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 = true to 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.