react-org-chart

repository·master·Indexed 43 days ago

https://github.com/unicef/react-org-chart

A high-performance React component for displaying organizational charts using D3-based SVG rendering. Version 0.3.4 supports large datasets, lazy-loading of nodes via loadParent and loadChildren functions, and interactive features including zooming and exporting to image or PDF.

Tokens
5.3K
Snippets
14
Records
19
Agent score
55%

What's inside react-org-chart

  1. Format tree data for OrgChart

    master

    The tree prop expects a nested object structure where each node contains a person object and metadata about its relationship to other nodes.

    Key fields per node:

    • id: Unique identifier for the node.
    • person: Object containing id, avatar (URL), department, name, title, and totalReports.
    • hasChild: Boolean indicating if the node has children.
    • hasParent: Boolean indicating if the node has a parent.
    • isHighlight: Boolean for visual highlighting.
    • children: Array of child node objects.
    {
      id: 1,
      person: {
        id: 1,
        avatar: 'https://s3.amazonaws.com/uifaces/faces/twitter/spbroma/128.jpg',
        department: '',
        name: 'Jane Doe',
        title: 'CEO',
        totalReports: 5
      },
      hasChild: true,
      hasParent: false,
      isHighlight: true,
      children: [
        {
          id: 2,
          person: {
            id: 2,
            avatar: 'https://s3.amazonaws.com/uifaces/faces/twitter/spbroma/128.jpg',
            department: '',
            name: 'John Foo',
            title: 'CTO',
            totalReports: 0
          },
          hasChild: false,
          hasParent: true,
          isHighlight: false,
          children: []
        }
      ]
    }
  2. Use the OrgChart component

    master

    To display an organizational chart, import OrgChart from @unicef/react-org-chart and provide a tree prop containing your nested data. You can also implement lazy-loading for parents and children, handle configuration changes, and bind custom UI elements to chart actions (like downloading or zooming) using specific ID props.

    import React from 'react'
    import OrgChart from '@unicef/react-org-chart'
    
    // ... inside a component class or function
    <OrgChart
      tree={tree}
      downloadImageId="download-image"
      downloadPdfId="download-pdf"
      onConfigChange={config => {
        // Setting latest config to state
        this.setState({ config: config })
      }}
      loadConfig={d => {
         // Called from d3 to get latest version of the config.
        const config = this.handleLoadConfig(d)
        return config
      }}
      loadParent={personData => {
        // getParentData(): To get the parent data from API
        const loadedParent = this.getParentData(personData)
        return Promise.resolve(loadedParent)
      }}
      loadChildren={personData => {
        // getChildrenData(): To get the children data from API
        const loadedChildren = this.getChildrenData(personData)
        return Promise.resolve(loadedChildren)
      }}
      loadImage={personData => {
        // getImage(): To get the image from API
        const image = getImage(personData.email)
        return Promise.resolve(image)
      }}
    />
  3. Develop the react-org-chart library

    master

    To contribute to or build the library from source:

    1. Clone and install dependencies:
    git clone https://github.com/unicef/react-org-chart.git
    cd react-org-chart
    npm install
    1. Build in watch mode:
    npm start
    1. Build for production:
    npm run build

    To run the included example project:

    cd example/
    npm install
    npm start
  4. Manage the org-chart-example project with Yarn scripts

    master

    The org-chart-example package is bootstrapped with Create React App. You can manage the development lifecycle using the following Yarn commands in the project directory:

    # Run the app in development mode at http://localhost:3000
    yarn start
    
    # Launch the test runner in interactive watch mode
    yarn test
    
    # Build the app for production in the `build` folder
    yarn build
    
    # Remove the single build dependency and copy all configuration files (Webpack, Babel, etc.) into the project
    # WARNING: This is a one-way operation.
    yarn eject
  5. Control zoom behavior via button IDs

    master

    The chart includes built-in zoom and pan functionality using D3. You can trigger specific zoom actions by attaching click events to DOM elements with the following IDs:

    • Zoom In: Use the ID provided in zoomInId.
    • Zoom Out: Use the ID provided in zoomOutId.
    • Reset Zoom (Zoom Extent): Use the ID provided in zoomExtentId. This calculates a scale and translation to fit the entire SVG content within the container dimensions.
  6. Configure chart dimensions and layout

    master

    The chart layout is driven by several configuration keys that control the spacing and size of the tree nodes. The lineType option also affects internal calculations for vertical depth:

    • If lineType is set to 'angle', lineDepthY is calculated as nodeHeight + 40.
    • For other line types, lineDepthY is calculated as nodeHeight + 60.

    Node dimensions are controlled via:

    • nodeWidth
    • nodeHeight
    • nodeSpacing (applied to both width and height in the D3 tree layout)
  7. Configure the Organizational Chart appearance and layout

    master

    The organizational chart component is styled and laid out using a configuration object. This object allows you to customize dimensions, spacing, colors, and line styles.

    Key configuration categories include:

    • Layout & Dimensions: Control nodeWidth, nodeHeight, nodeSpacing, and margin (top, right, bottom, left).
    • Node Styling: Customize nodeBorderRadius, avatarWidth, and internal padding (nodePaddingX, nodePaddingY).
    • Lines: Set the lineType (e.g., 'angle') and lineDepthY (the vertical height of the line connecting to child nodes).
    • Colors: Define backgroundColor, borderColor, nameColor, titleColor, and reportsColor.
    • Behavior: Toggle shouldResize for responsiveness and set animationDuration in milliseconds.
    const config = {
      margin: { top: 20, right: 20, bottom: 20, left: 20 },
      animationDuration: 350,
      nodeWidth: 140,
      nodeHeight: 180,
      nodeSpacing: 12,
      nodePaddingX: 16,
      nodePaddingY: 16,
      nodeBorderRadius: 4,
      avatarWidth: 48,
      lineType: 'angle',
      lineDepthY: 120,
      backgroundColor: '#fff',
      borderColor: '#c9c9c9',
      nameColor: '#222d38',
      titleColor: '#617080',
      reportsColor: '#92A0AD',
      shouldResize: true,
    }
  8. Configure OrgChart props

    master

    The OrgChart component accepts several props to control its appearance, data loading, and interactive features.

    Data and Layout

    • tree (Required): A nested Object representing the organizational hierarchy.
    • nodeWidth (Number): Width of each individual node.
    • nodeHeight (Number): Height of each individual node.
    • nodeSpacing (Number): Spacing between nodes.
    • animationDuration (Number): Animation duration in milliseconds.
    • lineType (String): Type of connecting lines ("angle" or "curve").

    Lazy Loading and API

    • loadParent(personData) (Function): Returns a Promise to load the parent of a node.
    • loadChildren(personData) (Function): Returns a Promise to load children of a node.
    • loadImage(personData) (Function): Returns a Promise to fetch an image for a person.

    Interaction and UI Binding

    The following props accept a String representing the id of a DOM element. When that element is clicked, the corresponding action is triggered:

    • downloadImageId: Triggers PNG download (default: "download-image").
    • downloadPdfId: Triggers PDF download (default: "download-pdf").
    • zoomInId: Triggers zoom in (default: "zoom-in").
    • zoomOutId: Triggers zoom out (default: "zoom-out").
    • zoomExtentId: Fits the whole chart to the screen (default: "zoom-extent").

    State Management

    • onConfigChange (Function): Callback triggered when the configuration changes.
    • loadConfig (Function): Function used to pass the latest configuration from state back to the component.
  9. Troubleshoot missing loadParent configuration

    master

    If you attempt to click a node that has hasParent: true but your configuration object does not contain a loadParent function, the following error will be logged to the console:

    react-org-chart.onClick: loadParent() not found in config

    Ensure that your configuration object passed to the chart component correctly exposes the loadParent method.

  10. Initialize the organizational chart with init()

    master

    The init function is the primary entrypoint for setting up the organizational chart. It merges user-provided options with a default configuration, targets a DOM element by its ID, and performs the initial D3.js tree layout and rendering.

    Key Requirements:

    • You must provide an id that matches an existing DOM element where the SVG will be injected.
    • You must provide data (passed via the data key in the options object) which represents the tree structure.

    Configuration Options:

    • id: (Required) The CSS selector/ID of the root DOM element.
    • data: The tree data object.
    • lineType: Determines the style of lines (e.g., 'angle').
    • margin: Object containing top, bottom, left, and right margins.
    • nodeWidth: Width of individual nodes.
    • nodeHeight: Height of individual nodes.
    • nodeSpacing: Spacing between nodes.
    • shouldResize: Boolean to enable/disable automatic resizing when the browser window changes.
    • zoomInId: ID of the DOM element used for zooming in.
    • zoomOutId: ID of the DOM element used for zooming out.
    • zoomExtentId: ID of the DOM element used to reset the zoom extent.
    • loadConfig: Function to load configuration (used during zoom extent resets).
    const { init } = require('@unicef/react-org-chart');
    
    init({
      id: '#chart-container',
      data: myTreeData,
      nodeWidth: 150,
      nodeHeight: 50,
      nodeSpacing: 20,
      lineType: 'angle',
      shouldResize: true,
      zoomInId: 'btn-zoom-in',
      zoomOutId: 'btn-zoom-out',
      zoomExtentId: 'btn-zoom-extent'
    });
  11. Customize node click behavior with `onPersonClick`

    master

    The onPersonClick configuration option allows you to intercept click events on individual nodes. This function is called before the default expansion/collapse logic or the asynchronous loadChildren logic.

    To prevent the default chart behavior (like expanding or collapsing a node), your onPersonClick handler must return false.

    Arguments:

    • datum: The data object associated with the clicked node.
    • event: The D3 event object.

    Return Value:

    • If false, the click handler is cancelled and no further actions (like loading children or toggling visibility) occur.
    // Example configuration
    const config = {
      onPersonClick: (datum, event) => {
        console.log('Person clicked:', datum);
        
        // Return false to prevent the node from expanding/collapsing
        if (someCondition) {
          return false;
        }
        
        return true;
      }
    };
  12. Implement parent node loading with onParentClick

    master

    When a user clicks on a parent node in the organizational chart, the onParentClick logic attempts to fetch and render new children. To use this functionality, your configuration object passed to the chart must include a loadParent function and a render function.

    Requirements

    1. loadParent(node): A function that takes the clicked node (the parent) and returns either a plain object containing the new children or a Promise that resolves to that object. The node being passed must have a hasParent: true property to trigger this logic.
    2. render(config): A function used to update the chart with the new data. The onParentClick handler calls render with an updated treeData object and a sourceNode (used for animation transitions).

    Data Flow

    • The loadParent function is called with the current node.
    • Once the data is retrieved, handleResult merges the new children into the existing tree structure.
    • The render function is then invoked to re-render the chart with the expanded tree.
    // Example configuration structure required for onParentClick to work
    const config = {
      loadParent: async (parentNode) => {
        const response = await fetch(`/api/children/${parentNode.id}`);
        const data = await response.json();
        return data; // Should contain a 'children' array
      },
      render: (updatedConfig) => {
        // Logic to update the component state with updatedConfig.treeData
        updateChartState(updatedConfig);
      }
    };