Search code examples
javascriptreactjsdagre

How can I control dagre layout to position nodes in a top-to-bottom tree with True branches on the left and False branches on the right?


I'm using the dagre layout algorithm to position nodes in a directed graph. The nodes represent branching logic, where the True branch should always be on the left side and the False branch on the right. However, only the immediate children of a branch have the hand property (TRUE or FALSE), and the subsequent children don't have this property.

Here is the relevant part of the layout function I currently have:

import type { LayoutAlgorithm } from '.';

const dagreLayout: LayoutAlgorithm = async (nodes, edges, options) => {
  const dagreGraph = new dagre.graphlib.Graph().setDefaultEdgeLabel(() => ({}));
  dagreGraph.setGraph({
    rankdir: options.direction, // Top-to-bottom layout
    nodesep: options.spacing[0],
    ranksep: options.spacing[1],
  });

  nodes.forEach((node) => {
    dagreGraph.setNode(node.id, {
      width: node.width ?? 0,
      height: node.height ?? 0,
    });
  });

  edges.forEach((edge) => {
    dagreGraph.setEdge(edge.source, edge.target);
  });

  dagre.layout(dagreGraph);

  const nextNodes = nodes.map((node) => {
    const { x, y } = dagreGraph.node(node.id);
    const position = {
      x: x - (node.width ?? 0) / 2,
      y: y - (node.height ?? 0) / 2,
    };

    return { ...node, position };
  });

  return { nodes: nextNodes, edges };
};

export default dagreLayout;

Problem: I want to ensure that:

  1. True branch nodes always appear on the left side of their parent.
  2. False branch nodes always appear on the right side of their parent.

Question:

How can I control the positions of the child nodes to reflect this branching logic while using the dagre layout? Is there a way to enforce the True/False position behavior based on the node's hand property?

Only the immediate children of a node have the hand property (TRUE or FALSE). Subsequent children won't have this property, so I need a way to enforce this rule while keeping the layout top-to-bottom. How can I modify the dagre layout logic to ensure this?


Solution

  • After extensive research, it appears that dagre doesn't support this functionality. Therefore, I had to switch to `elkjs, which offers much more control over graph structure and layout. You can find more details and solutions discussed in this GitHub issue.