JavaScript in 10 minutes
Mount a live diagram with render, then use the returned DiagramInstance to fit, observe, save, and restore it.
Grafloria has one headless model underneath its JavaScript and framework bindings. The renderer connects that model to the canvas; the instance is the live handle you keep for later operations.
Prerequisites
- A modern browser with ES modules.
- Node.js and npm for installing the packages and running an ESM development server.
- No framework. The packages are ESM; the starter below uses Vite.
1. Install the packages
bashnpm install @grafloria/element @grafloria/renderer @grafloria/engine npm install --save-dev vite
@grafloria/element provides the JavaScript render() entry point. The renderer and engine satisfy its peer dependencies.
Add these scripts to package.json:
json{
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build"
}
}
2. Give the diagram a sized target
Create index.html with a container that has a real height. A diagram in a zero-height element has no area in which to draw.
html<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Grafloria JavaScript quick start</title>
<style>
html, body, #canvas { margin: 0; height: 100%; }
#canvas { width: 100%; height: 400px; }
#actions { position: fixed; z-index: 1; top: 1rem; left: 1rem; }
</style>
</head>
<body>
<div id="actions">
<button id="save" type="button">Save</button>
<button id="load" type="button">Load</button>
</div>
<div id="canvas" style="width: 100%; height: 400px;"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
3. Render real nodes and an edge
Create src/main.js. Pass a data spec first and the target element second. The call returns the live instance, and fitView: true frames the initial content.
jsimport { render } from '@grafloria/element';
const canvas = document.getElementById('canvas');
const saveButton = document.getElementById('save');
const loadButton = document.getElementById('load');
if (!canvas || !saveButton || !loadButton) {
throw new Error('The diagram controls are missing');
}
canvas.style.width = '100%';
canvas.style.height = '400px';
const api = render({
nodes: [
{
id: 'a',
position: { x: 60, y: 80 },
size: { width: 180, height: 80 },
data: { label: 'Ingest' },
},
{
id: 'b',
position: { x: 380, y: 80 },
size: { width: 180, height: 80 },
data: { label: 'Publish' },
},
],
edges: [{ id: 'e1', source: 'a', target: 'b' }],
}, canvas, { fitView: true });
api.on('node:doubleclick', () => {
console.log('A node was double-clicked');
});
saveButton.addEventListener('click', () => {
localStorage.setItem('diagram-text', api.exportText());
});
loadButton.addEventListener('click', () => {
const saved = localStorage.getItem('diagram-text');
if (saved !== null) {
api.loadText(saved);
api.fitView();
api.renderNow();
}
});
Run the page with:
bashnpm run dev
The browser shows two labelled nodes connected by an edge. You can drag nodes, draw connections, pan, and zoom. Double-clicking a node logs a message. render() accepts a data object, not Mermaid text; use loadText() when the input is Mermaid-compatible text.
4. Save and restore the document
The Save button stores the string returned by exportText(). The export is Mermaid-compatible and includes Grafloria's lossless sidecar by default, so positions and styling can round-trip. Load passes that string to loadText(), which reconciles it into the mounted diagram, then fitView() and renderNow() frame and repaint the restored content.
For JSON document persistence, use api.getModel() with the engine's serializer; the text round-trip above keeps this first example at the instance front door.
What you have at the end
You have a mounted, interactive diagram and one instance that lets your application:
- subscribe to diagram events with
on(); - frame content with
fitView(); - export and restore Mermaid-compatible text with
exportText()andloadText(); - force an immediate repaint with
renderNow().
When the page tears down, call api.dispose() from your application’s unmount or close handler. Do not dispose it immediately after rendering: disposal removes the live diagram.
Where next
- The element vs
render()explains when to use the custom element instead. - Save and restore diagrams covers document persistence in depth.
- Events and interaction covers the instance event model.
- Try the live demo gallery.
Was this page helpful?