Skip to content
D
Documentation

Build ER and UML diagrams

how-to
4 min readUpdated

Use the ER and UML kits when your schema or class model already exists as data and you want Grafloria to render its cards, relationship notation, and interactive canvas. The kits return diagram specs; render() mounts those specs in JavaScript, while framework bindings mount the same specs in their host components.

Build an ER diagram

Pass entities and relationships to erDiagram(). Each entity becomes a table card with typed column rows and PK/FK badges. Relationships draw as orthogonal edges with cardinality markers; endpoints written as ENTITY.column attach to that column's row. The kit provides row selection by default.

The JavaScript example connects CUSTOMER.id to ORDER.customer_id. It renders two table cards, their key badges, and a one-to-many relationship with its label. Give the mounted canvas a real height so it has space to draw. The Angular sample uses column-qualified ends too, so each relationship endpoint attaches to the matching row.

The JavaScript samples create and append a 500-pixel host before mounting. React and Vue mount the same ER data through their framework hosts; Angular uses a separate AUTHOR-to-BOOK example to show column-qualified endpoints.

The React GrafloriaDiagram and Vue GrafloriaDiagram bindings accept the kit spec directly. Angular uses GrafloriaDiagramComponent. Qwik uses GrafloriaDiagram with a serializable RenderSpec of nodes and edges; that Qwik variant draws generic nodes and labeled edges, not the kits' HTML cards, key badges, cardinality markers, UML relationship markers, or multiplicity labels. The ER builder accepts ErDiagramOptions; the UML builder accepts UmlDiagramOptions.

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

const spec = erDiagram({
  entities: [
    { id: 'CUSTOMER', name: 'Customer', position: { x: 60, y: 80 }, columns: [
      { name: 'id', type: 'int', pk: true },
      { name: 'email', type: 'varchar' },
    ] },
    { id: 'ORDER', name: 'Order', position: { x: 390, y: 80 }, columns: [
      { name: 'id', type: 'int', pk: true },
      { name: 'customer_id', type: 'int', fk: true },
      { name: 'placed_at', type: 'date' },
    ] },
  ],
  relationships: [
    {
      from: 'CUSTOMER.id',
      to: 'ORDER.customer_id',
      label: 'places',
      cardinality: 'one-to-many',
    },
  ],
});

const host = document.createElement('div');
host.style.cssText = 'display:block; width:100%; height:500px';
document.body.append(host);
const instance = render(spec, host);
instance.fitView(40);

To connect tables without pinning to a specific row, use the entity IDs as relationship ends, such as { from: 'CUSTOMER', to: 'ORDER', label: 'places' }. Use column-qualified ends for FK-to-PK relationships: the column name must exist on the named entity or the kit throws an error when it builds the spec. The default cardinality is one-to-many; choose another supported cardinality when the model calls for it.

Open the live ER diagram demo to see the rendered table cards, key badges, and relationship markers.

For multiple foreign keys between the same tables, self-references, junction tables, and optional or mandatory cardinalities, see the advanced ER demo. Its column-level ends and cardinality choices use the same entity and relationship data model.

Build a UML class diagram

Pass class definitions and relationships to umlDiagram(). Classes render in compartments for the class name, attributes, and methods. An abstract class name is italicized; relationship kinds supply their UML marker and line style. Multiplicity values add positioned labels to the live links.

This example renders an abstract Animal, its Dog subclass, and an Owner aggregation. The kit draws the three-compartment cards, inheritance triangle, and hollow diamond; render() runs the kit's finalization hook when it mounts a spec.

The React and Vue samples pass the spec to their framework binding. Angular mounts it with GrafloriaDiagramComponent.

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

const spec = umlDiagram({
  classes: [
    {
      id: 'Animal',
      abstract: true,
      position: { x: 180, y: 50 },
      attributes: ['# name: String'],
      methods: ['+ speak(): void'],
    },
    {
      id: 'Dog',
      position: { x: 180, y: 300 },
      attributes: ['+ breed: String'],
      methods: ['+ fetch(): void'],
    },
    {
      id: 'Owner',
      position: { x: 500, y: 300 },
      attributes: ['+ name: String'],
      methods: ['+ adopt(dog): void'],
    },
  ],
  relationships: [
    { from: 'Dog', to: 'Animal', kind: 'inheritance' },
    { from: 'Owner', to: 'Dog', kind: 'aggregation', label: 'owns', multiplicity: ['1', '0..*'] },
  ],
});

const host = document.createElement('div');
host.style.cssText = 'display:block; width:100%; height:500px';
document.body.append(host);
const instance = render(spec, host);
instance.fitView(40);

Relationship kinds supported by the UML kit are inheritance, realization, association, directed-association, aggregation, composition, and dependency. The kit draws each kind's notation, including dashed lines for realization and dependency, diamonds at the source end for aggregation and composition, and an open target arrow for directed association. Provide multiplicity: ['from', 'to'] to add a chip at each endpoint. The class diagram demo shows the basic class-card and relationship pattern.

The UML relationships demo shows all seven relationship kinds, multiplicities, stereotypes, and their rendered markers.

Use node and edge data directly

Use the kits when you want their table or class cards and relationship notation. If your ER or UML model is already expressed as graph data, mount NodeSpec nodes and EdgeSpec edges directly. The resulting canvas uses regular diagram nodes and links; it does not add the kits' HTML cards, PK/FK badges, UML markers, or multiplicity chips.

For the JavaScript and framework mounting patterns, see Build runnable workflows. Here, ordinary graph nodes carry class members as label text, so the canvas shows the relationships without UML compartments, markers, or multiplicity chips.

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

const nodes = [
  { id: 'CUSTOMER', position: { x: 60, y: 80 }, size: { width: 240, height: 90 }, label: 'Customer · id: int (PK) · email: varchar' },
  { id: 'ORDER', position: { x: 390, y: 80 }, size: { width: 260, height: 90 }, label: 'Order · id: int (PK) · customer_id: int (FK)' },
];
const edges = [{ id: 'places', source: 'CUSTOMER', target: 'ORDER', label: 'places' }];
const host = document.getElementById('diagram');
if (!host) throw new Error('Missing #diagram');
host.style.height = '500px';
const instance = render({ nodes, edges }, host);
instance.fitView(40);

Options that matter

OptionTypeDefaultWhat it does
relationshipsER relationship records or UML relationship records[]Describes the connections between entity or class IDs. ER relationship ends can include a column name; UML relationships can set a kind and multiplicities.
cardinality (ER)Named cardinality or { tail: string; head: string }'one-to-many'Chooses ER endpoint markers. Named values include one-to-one, many-to-many, one-to-zero-or-many, and one-to-one-or-many.
multiplicity (UML)[string, string]NoneAdds the from-end and to-end multiplicity labels.
rowSelectionbooleantrueEnables member/column row selection. Set false to opt out.
editablebooleanfalseAdds in-canvas rename, add, and delete controls for entity columns or class members. Edits are undoable.
height (entity or class)numberContent-sizedFixes a card's height; content exceeding it scrolls inside the card.

Pitfalls

  • Column-qualified ER relationship ends must name an existing entity and column. A missing entity or field causes erDiagram() to throw while building its spec.
  • The UML multiplicity labels need a live diagram model. Mount the spec; render() runs its finalize hook, which adds the labels after the links exist.
  • Framework components need a parent with a nonzero height. The examples set a 500-pixel canvas height; adapt that value to your layout.
  • The kit's UML relationship vocabulary does not include self-association. For the ER kit's supported self-reference pattern, see the advanced ER demo; a custom UML self-loop needs edge-level modeling beyond this kit.

Was this page helpful?