Skip to content
D
Documentation

Apply auto-layout

how-to
3 min readUpdated

Use a mounted graph's layout registry to arrange its nodes, then fit the resulting diagram into the canvas. The same graph model drives the JavaScript, Angular, React, and Vue bindings.

Choose a layout

Use the mounted DiagramInstance as the facade for the live diagram. In JavaScript, call getEngine() and await the engine's layout operation. The call changes the live model and returns a layout result; call renderNow() before fitting when you need the repaint immediately.

Registered names include auto, elk, dagre, layered, tree, grid, circular, radial, force, spectral, and community. Use auto when you want the engine to choose from the graph's shape. Use dagre, layered, or elk for pipelines and DAGs; use tree for hierarchies; use grid, circular, or radial for uniform collections; and use force, community, or spectral for networks. An unknown name throws instead of silently leaving the graph unchanged.

The object form supplies layout options. nodeSpacing and rankSpacing control the gaps used by the shipped layered layouts.

JavaScript

Mount real data with render, run the chosen layout, repaint, and frame all content. The host has an explicit height so the fitted diagram has a visible canvas.

js
import { render } from '@grafloria/element';

const host = document.querySelector('#diagram');
if (!(host instanceof HTMLElement)) throw new Error('The #diagram element is required');

const spec = {
  nodes: [
    { id: 'root', position: { x: 0, y: 0 }, size: { width: 130, height: 52 }, label: 'Root' },
    { id: 'left', position: { x: 0, y: 0 }, size: { width: 130, height: 52 }, label: 'Left' },
    { id: 'right', position: { x: 0, y: 0 }, size: { width: 130, height: 52 }, label: 'Right' },
  ],
  edges: [
    { id: 'root-left', source: 'root', target: 'left' },
    { id: 'root-right', source: 'root', target: 'right' },
  ],
};

host.style.height = '400px';

const instance = render(spec, host);

async function arrange() {
  const result = await instance.getEngine().layout('dagre', {
    nodeSpacing: 40, rankSpacing: 80,
  });
  instance.renderNow();
  instance.fitView(40);
  console.log(result.bounds);
}

void arrange();

The three nodes start at the same position, then appear as a left-to-right tree. result.bounds is the bounding box of the laid-out graph, while fitView(40) frames all content with 40 world units of padding.

Framework bindings

The declarative layout prop runs the layout when its value changes. It does not re-run when node data changes, so it does not fight a user's drag. Set fitView on the flow to fit the rendered graph.

ts
import { Component } from '@angular/core';
import { DiagramCanvasComponent } from '@grafloria/angular';
import type { EdgeSpec, NodeSpec } from '@grafloria/renderer';

@Component({
  standalone: true,
  imports: [DiagramCanvasComponent],
  template: `
    <grafloria-diagram-canvas [(nodes)]="nodes" [(edges)]="edges"
      [layout]="layout" [plugins]="true" style="display:block;height:100vh" />
  `,
})
export class LayoutDemo {
  layout = { name: 'dagre', options: { nodeSpacing: 40, rankSpacing: 80 } };
  nodes: NodeSpec[] = [
      { id: 'root', position: { x: 0, y: 0 }, size: { width: 130, height: 52 }, label: 'Root' },
    { id: 'left', position: { x: 0, y: 0 }, size: { width: 130, height: 52 }, label: 'Left' },
    { id: 'right', position: { x: 0, y: 0 }, size: { width: 130, height: 52 }, label: 'Right' },
  ];
  edges: EdgeSpec[] = [
    { id: 'root-left', source: 'root', target: 'left' },
    { id: 'root-right', source: 'root', target: 'right' },
  ];
}

Angular's [plugins]="true" adds canvas controls, including Fit. After the layout completes, use that control to frame the tree. In the other bindings, fitView performs the same framing as part of the mounted flow.

For an imperative rerun, capture the instance through the binding's initialization callback and call instance.getEngine().layout(...), followed by instance.fitView(40). Angular exposes the same operation as applyLayout() on its canvas component; its layoutDone output fires after the operation completes.

Options that matter

OptionTypeDefaultWhat it does
layoutstring | { name: string; options?: Record<string, unknown> }—Selects a registered algorithm and optional settings.
directionlayout option—Sets the flow direction for supported layouts.
nodeSpacinglayout option—Sets spacing between nodes where supported.
rankSpacinglayout option—Sets spacing between ranks where supported.
fitViewboolean—Fits the mounted flow's content into its view.

Pitfalls

  • Give the canvas host a real height. A percentage height resolves to zero when its ancestors have no height, leaving nothing to fit.
  • A declarative layout reacts to changes in the layout value, not to node changes. Call the instance's engine for an explicit rerun after editing the graph.
  • elk loads its heavier implementation on first use. Choose it when its layered and port-aware behavior matters; use a smaller shipped layout for a lightweight arrangement.
  • Layout changes node positions and invalidates stale edge routes. Repaint the instance before measuring or exporting the result.

See it running

Open the auto-layout demo to switch between algorithms on a graph whose nine nodes begin stacked at the origin. The demo runs a layout, repaints, and fits the view after each switch.

For a fixed top-down hierarchy, see the Dagre tree demo. For incremental placement that preserves the existing mental map, see dynamic layouting.

Was this page helpful?

Apply auto-layout — Grafloria · GPT-5.6 Luna