The source code for this demo is available on Github.
https://github.com/jsplumb-demonstrations/flowchart-builder
If you haven't got a license for JsPlumb, we offer 30 day evaluations.
Start a free trialWhat is a Flowchart and how can I develop one using JsPlumb?
A flowchart is a type of diagram that represents a workflow, process or system, using various symbols and arrows. It is a visual tool for people to design and document the flow of logic.
A flowchart consists of a set of blocks connected by edges. The blocks in some flowchart can represent a wide variety of concepts. JsPlumb ships with a set of flowchart shapes that represent many of the common concepts people want to use - things such as processes, questions, decisions, inputs, outputs, etc.
The source code for this demonstration is available on Github, and it uses a number of JsPlumb's components such as the miniview, object inspector, controls component and surface component, to provide a solid basis for an Angular, React, Vue, Svelte, Typescript or Javascript app.
Angular Flowchart
JsPlumb's deep Angular integration makes building an Angular Flowchart very simple. The Flowchart builder starter app uses our ControlsComponent, SurfaceComponent, MiniviewComponent and Angular service to provide a fully featured Flowchart. Tested with Angular 16, 17, 18 and 19.
- Flowchart
- View
- Render Options
<div class="jtk-demo-main" id="jtk-demo-flowchart">
<div class="jtk-demo-canvas">
<jsplumb-surface [view]="view"
[renderParams]="renderParams"
[toolkitParams]="toolkitParams"
url="/assets/copyright.json"></jsplumb-surface>
<jsplumb-controls></jsplumb-controls>
<jsplumb-export-controls [imageOptions]="imageExportOptions"></jsplumb-export-controls>
<jsplumb-miniview></jsplumb-miniview>
</div>
<div class="jtk-demo-rhs">
<!-- the node palette -->
<div class="sidebar node-palette">
<jtk-shape-palette [dataGenerator]="dataGenerator" [initialSet]="initialShapeSet"></jtk-shape-palette>
</div>
<app-inspector></app-inspector>
<div class="description">
<p>
This sample application is a builder for flowcharts.
</p>
</div>
</div>
</div>
view = {
nodes: {
[DEFAULT]:{
component:NodeComponent,
// node can support any number of connections.
maxConnections: -1,
events: {
[EVENT_TAP]: (params) => {
// if zero nodes currently selected, or the shift key wasnt pressed, make this node the only one in the selection.
if (this.toolkit.getSelection()._nodes.length < 1 || params.e.shiftKey !== true) {
this.toolkit.setSelection(params.obj)
} else {
// if multiple nodes already selected, or shift was pressed, add this node to the current selection.
this.toolkit.addToSelection(params.obj)
}
}
}
}
},
edges: {
[DEFAULT]: {
deleteButton:true, // show a delete button
connector: {
type: OrthogonalConnector.type,
options: {
cornerRadius: 3,
alwaysRespectStubs: true,
stub: GRID_SIZE.w
}
},
cssClass: CLASS_FLOWCHART_EDGE,
outlineWidth: 10,
events: {
[EVENT_CLICK]: (p) => {
if (!p.e.defaultPrevented) {
this.toolkit.setSelection(p.edge)
}
}
},
overlays:[
{
type:LabelOverlay.type,
options:{
useHTMLElement:false,
cssClass:CLASS_EDGE_LABEL,
label:"{{label}}",
location:0.5
}
}
]
}
}
}
renderParams: AngularRenderOptions = {
// see `edge-mappings.js` for details.
propertyMappings:{
edgeMappings:edgeMappings()
},
grid: {
size: GRID_SIZE
},
events: {
[EVENT_CANVAS_CLICK]: (e) => {
this.toolkit.clearSelection()
}
},
consumeRightClick: false,
dragOptions: {
filter: ".node-action, .node-action i"
},
plugins: [
DrawingToolsPlugin.type,
{
type:LassoPlugin.type,
options: {
invert:true
}
},
{
type:BackgroundPlugin.type,
options:GRID_BACKGROUND_OPTIONS
}
],
useModelForSizes:true,
zoomToFit:true,
defaults:{
edgesAvoidVertices:true
},
magnetize:{
constant:true,
trackback:true
}
}
React Flowchart
React Flowcharts with JsPlumb are a snap. Our Flowchart builder starter app uses JsPlumb's advanced React integration with its providers and support for functional components, to give you a solid foundation on which to base your app. Tested with React 16, 17, 18 and 19.
- Flowchart
- View
- Render Options
<div className="jtk-demo-canvas">
<SurfaceProvider>
<SurfaceComponent shapeLibrary={shapeLibrary}
renderOptions={renderParams}
viewOptions={view}
ref={ surfaceComponent }>
<ControlsComponent/>
<ExportControlsComponent/>
<MiniviewComponent/>
</SurfaceComponent>
<div className="jtk-demo-rhs">
<ShapeLibraryPaletteComponent className="node-palette" dataGenerator={dataGenerator} initialSet={FLOWCHART_SHAPES.id}/>
<Inspector edgeMappings={edgeMappings()}/>
</div>
</SurfaceProvider>
</div>
const view = {
nodes: {
[DEFAULT]: {
jsx: (ctx) => {
return <NodeComponent ctx={ctx}/>
},
// node can support any number of connections.
maxConnections: -1,
events: {
[EVENT_TAP]: (params) => {
// if zero nodes currently selected, or the shift key wasnt pressed, make this node the only one in the selection.
if (toolkit.current.getSelection()._nodes.length < 1 || params.e.shiftKey !== true) {
toolkit.current.setSelection(params.obj)
} else {
// if multiple nodes already selected, or shift was pressed, add this node to the current selection.
toolkit.current.addToSelection(params.obj)
}
}
}
}
},
// There are two edge types defined - 'yes' and 'no', sharing a common
// parent.
edges: {
[DEFAULT]: {
deleteButton:true, // show a delete button
connector: {
type: OrthogonalConnector.type,
options: {
stub:GRID_SIZE.w
}
},
cssClass:CLASS_FLOWCHART_EDGE,
labelClass:CLASS_EDGE_LABEL,
label:"{{label}}",
outlineWidth:10,
events: {
[EVENT_CLICK]: (params) => {
if (!params.e.defaultPrevented) {
toolkit.current.setSelection(params.edge)
}
}
},
overlays:[
{
type:LabelOverlay.type,
options:{
useHTMLElement:false,
cssClass:CLASS_EDGE_LABEL,
label:"{{label}}",
location:0.5
}
}
]
}
}
}
const renderParams = {
grid:{
size:GRID_SIZE
},
events: {
[EVENT_CANVAS_CLICK]: (e) => {
toolkit.current.clearSelection()
}
},
propertyMappings:{
edgeMappings:edgeMappings()
},
consumeRightClick: false,
dragOptions: {
filter: ".node-action, .node-action i"
},
plugins:[
DrawingToolsPlugin.type,
{
type:LassoPlugin.type,
options: {
lassoInvert:true,
lassoEdges:true
}
},
{
type:BackgroundPlugin.type,
options:GRID_BACKGROUND_OPTIONS
}
],
// set the size of elements from the width/height values in their backing data
useModelForSizes:true,
// on load, zoom the dataset so its all visible
zoomToFit:true,
defaults:{
edgesAvoidVertices:true
},
magnetize:{
constant:true,
trackback:true
}
}
Typescript Flowchart
JsPlumb is written in Typescript and ships with a full set of type definitions, for a seamless Typescript development experience.
JsPlumb's Surface component is the heart of the Flowchart, and JsPlumb ships a large number of useful helper components such as the Miniview, the Controls component for managing zoom, undo/redo etc, the ShapeLibraryPalette, which lets you easily configure drag/drop of new elements, plus a long list of plugins.
Our Typescript Flowchart builder starter app provides you with everything you need to get a solid start, and is easily extensible.
- Code
- HTML
import { newInstance, FLOWCHART_SHAPES,
BASIC_SHAPES,
ShapeLibraryImpl,
ControlsComponent,
ShapeLibraryPalette } from "@jsplumbtoolkit/browser-ui"
export class MyFlowchart() {
constructor() {
const shapeLibrary = new ShapeLibraryImpl([FLOWCHART_SHAPES, BASIC_SHAPES]);
const toolkit = newInstance()
const surface = toolkit.render(document.querySelector("#canvas"), {
view:{
nodes:{
default:{
template:`<div data-jtk-target="true"><jtk-shape/></div>`
}
}
},
grid: { w:50, h:50 },
magnetize:{
constant:true,
trackback:true
} ,
shapes:{
library:shapeLibrary
},
defaults:{
edgesAvoidVertices:true
}
})
new ControlsComponent(document.querySelector("#controls"), surface)
new ShapeLibraryPalette ({
container:document.querySelector("#palette"),
initialSet:FLOWCHART_SHAPES.id,
surface
})
}
}
<div id="flowchart-wrapper">
<div id="canvas">
<div id="controls"></div>
</div>
<div id="palette"></div>
</div>
Vue Flowchart
It's easy to build a Vue Flowchart with JsPlumb - we've done most of the hard work for you in our Vue Flowchart builder starter app
Our Vue Flowchart takes advantage of JsPlumb's ability to integrate deeply with Vue, using Vue components to render nodes, and several of JsPlumb's Vue helper components and plugins such as the ControlsComponent, MiniviewComponent, ShapeLibraryComponent, GeneratedGridBackground plugin, Lasso plugin, and more. With JsPlumb's Vue Flowchart all you need to do is drop it into your app and off you go.
<script>
import { defineComponent } from "vue";
import { FLOWCHART_SHAPES, BASIC_SHAPES, ShapeLibraryImpl, DrawingToolsPlugin} from "@jsplumbtoolkit/browser-ui"
import { loadSurface, DEFAULT_VUE_SURFACE_ID } from "@jsplumbtoolkit/browser-ui-vue3"
let surface
let toolkit
const shapeLibrary = new ShapeLibraryImpl([FLOWCHART_SHAPES, BASIC_SHAPES])
export default defineComponent({
name:"flowchart",
mounted() {
loadSurface(DEFAULT_VUE_SURFACE_ID, (s) => {
surface = s;
toolkit = surface.toolkitInstance;
})
},
methods:{
viewParams:function() {
return {
nodes:{
default:{
component:NodeComponent
}
}
}
},
renderParams:function() {
return {
shapes:{
library:shapeLibrary
},
grid:{
size:{w:50, h:50}
},
plugins:[
DrawingToolsPlugin.type
],
defaults:{
edgesAvoidVertices:true
},
magnetize:{
constant:true,
trackback:true
},
// set the size of elements from the width/height values in their backing data
useModelForSizes:true,
// on load, zoom the dataset so its all visible
zoomToFit:true
}
}
}
</script>
<template>
<div id="app">
<div class="jtk-demo-canvas">
<SurfaceComponent :renderOptions="this.renderParams()"
:viewOptions="this.viewParams()"
url="copyright.json">
</SurfaceComponent>
<ControlsComponent/>
<MiniviewComponent/>
</div>
</div>
</template>
Svelte Flowchart
JsPlumb's Svelte integration has everything you need to quickly build a Svelte Flowchart, and what's great is we've already pulled it all together for you in our Svelte Flowchart builder starter app
Our Svelte Flowchart uses several of JsPlumb's Svelte components, including the SurfaceComponent, ControlsComponent, MiniviewComponent and ShapeLibraryPaletteComponent, and it also takes advantage of our SurfaceProvider, which works like a provider in React - use it to enclose several child components and a shared context is established, allowing all of the component to access a single dataset without the need for manually plugging them all together.
<script>
import { FLOWCHART_SHAPES, BASIC_SHAPES, ShapeLibraryImpl,
DrawingToolsPlugin, LassoPlugin, BackgroundPlugin } from "@jsplumbtoolkit/browser-ui"
const shapeLibrary = new ShapeLibraryImpl([FLOWCHART_SHAPES, BASIC_SHAPES])
const view = {
nodes:{
[DEFAULT]:{
component:NodeComponent
}
}
}
const renderOptions = {
grid:{
size:{w:50, h:50}
},
dragOptions: {
filter: ".jtk-draw-handle, .node-action, .node-action i"
},
plugins:[
DrawingToolsPlugin.type,
{
type:LassoPlugin.type,
options: {
lassoInvert:true,
lassoEdges:true
}
},
{
type:BackgroundPlugin.type,
options:GRID_BACKGROUND_OPTIONS
}
],
// set the size of elements from the width/height values in their backing data
useModelForSizes:true,
// on load, zoom the dataset so its all visible
zoomToFit:true
}
</script>
<div>
<SurfaceProvider>
<SurfaceComponent shapeLibrary={shapeLibrary}
renderOptions={renderOptions}
viewOptions={view}
className="jtk-demo-canvas"
url="/copyright.json">
<ControlsComponent/>
<ExportControlsComponent/>
<MiniviewComponent/>
</SurfaceComponent>
<div class="jtk-demo-rhs">
<ShapeLibraryPaletteComponent className="node-palette" dataGenerator={dataGenerator} initialSet={FLOWCHART_SHAPES.id}/>
<InspectorComponent inspectors={inspectorMap} className="jtk-inspector"/>
</div>
</SurfaceProvider>
</div>



















