Call Flow
The source code for this demo is available on Github.
https://github.com/jsplumb-demonstrations/callflow
If you haven't got a license for JsPlumb, we offer 30 day evaluations.
Start a free trialWhat is a Callflow Builder and how can I develop one using JsPlumb?
A Callflow Builder assists in the creation and management of call flows, for adding programmable logic to voice applications using a drag and drop interface.
This starter app provides you a solid foundation you can use to develop your own Callflow Builder
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 Callflow Builder
JsPlumb's deep Angular integration makes building an Angular Callflow Builder very simple. The Callflow builder starter app uses our ControlsComponent, SurfaceComponent, MiniviewComponent and Angular service to provide a fully featured application. Tested with Angular 16, 17, 18 and 19.
- Callflow
- View
- Render Options
<div class="jtk-demo-main" id="jtk-demo-callflow">
<!-- main drawing area -->
<div class="jtk-demo-canvas">
<jsplumb-surface [toolkitParams]="toolkitParams"
[renderParams]="renderParams"
[view]="view"
url="/assets/callflow.json"/>
<jsplumb-controls/>
<jsplumb-miniview/>
</div>
<div class="jtk-demo-rhs">
<!-- the node palette -->
<div class="jtk-callflow-palette"
jsplumb-surface-drop
selector=".jtk-callflow-palette-item"
[dataGenerator]="dataGenerator">
<div *ngFor="let nodeType of nodeTypes" class="jtk-callflow-palette-item" [attr.data-jtk-type]="nodeType.type" title="Drag to add new">
<div class="jtk-callflow-node-icon"></div>
{{nodeType.label}}
</div>
</div>
</div>
<app-inspector [showCloseButton]="true"/>
</div>
view:AngularViewOptions = {
nodes:{
// abstract parent mapping with an event binding to the TAP event - user taps a node
// and it is set as the Toolkit's current selection.
[SELECTABLE]:{
events:{
[EVENT_TAP]:(p:{obj:Base, toolkit:BrowserUIAngular}) => {
p.toolkit.setSelection(p.obj)
}
}
},
[DEFAULT]:{
// The default mapping uses BasicNodeComponent, which shows a label and
// optionally some text. If there is no other mapping found for a node this
// one is used.
parent:SELECTABLE,
component:BaseCallFlowNodeComponent
},
// Some more complex nodes have their own components...
[TYPE_REQUEST]:{
parent:SELECTABLE,
component:RequestNodeComponent
},
[TYPE_SET_VARIABLES]:{
parent:SELECTABLE,
component:SetVariablesComponent
},
[TYPE_CONDITIONS]:{
parent:SELECTABLE,
component:ConditionsComponent
},
[TYPE_CALL_FORWARD]:{
parent:SELECTABLE,
component:CallForwardingComponent
},
[TYPE_KEYPAD_ENTRY]:{
parent:SELECTABLE,
component:KeypadEntryComponent
}
},
edges:{
default:{
// edges have a delete button that is visible on hover (although on
// a touch device JsPlumb will ensure it is always visible)
deleteButton:OVERLAY_VISIBILITY_HOVER,
overlays:[
{
// show a plain arrow at the end of each edge.
type:PlainArrowOverlay.type,
options:{
location:1,
width:10,
length:10
}
}
]
}
}
}
renderParams:AngularRenderOptions = {
// zoom content to fit on load
zoomToFit:true,
// allow user to right-click to inspect (in prod you probably want to leave this out)
consumeRightClick:false,
defaults:{
// paint a transparent outline around connectors, to make it easier to hover
// to see the delete button.
paintConnectorOutline:true,
// anchors are always on the right edge of the source and the left edge of the target
anchors:[AnchorLocations.Right, AnchorLocations.Left],
// use an orthogonal connector with a 5px corner radius
connector:{
type:OrthogonalConnector.type,
options:{
cornerRadius:5
}
}
}
}
React Callflow Builder
Creating a Callflow Builder with JsPlumb is a snap. Our Callflow 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.
- Callflow
- View
- Render Options
<div className="jtk-demo-main" id="jtk-demo-callflow">
<SurfaceProvider>
<div className="jtk-demo-canvas">
<SurfaceComponent toolkit={toolkit}
renderOptions={renderOptions}
viewOptions={view}
url="/callflow.json"/>
<ControlsComponent/>
<MiniviewComponent/>
</div>
<CallFlowPalette/>
<CallflowInspector toolkit={toolkit}/>
</SurfaceProvider>
</div>
const view = {
nodes:{
// abstract parent mapping with an event binding to the TAP event - user taps a node
// and it is set as the Toolkit's current selection.
[SELECTABLE]:{
events:{
[EVENT_TAP]:(p:{obj:Base, toolkit:BrowserUIReact}) => {
toolkit.setSelection(p.obj)
}
}
},
[DEFAULT]:{
// The default mapping uses `BasicNodeComponent`, which shows a label and
// optionally some text. If there is no other mapping found for a node this
// one is used.
parent:SELECTABLE,
jsx:(ctx:JsxWrapperProps<Node>) => <BasicNodeComponent ctx={ctx}/>
},
// Some more complex nodes have their own components...
[TYPE_SET_VARIABLES]:{
parent:SELECTABLE,
jsx:(ctx:JsxWrapperProps<Node>) => <SetVariablesComponent ctx={ctx}/>
},
[TYPE_REQUEST]:{
parent:SELECTABLE,
jsx:(ctx:JsxWrapperProps<Node>) => <RequestNodeComponent ctx={ctx}/>
},
[TYPE_KEYPAD_ENTRY]:{
parent:SELECTABLE,
jsx:(ctx:JsxWrapperProps<Node>) => <KeypadEntryComponent ctx={ctx}/>
},
[TYPE_CONDITIONS]:{
parent:SELECTABLE,
jsx:(ctx:JsxWrapperProps<Node>) => <ConditionsComponent ctx={ctx}/>
},
[TYPE_CALL_FORWARD]:{
parent:SELECTABLE,
jsx:(ctx:JsxWrapperProps<Node>) => <CallForwardingComponent ctx={ctx}/>
}
},
edges:{
[DEFAULT]:{
// edges have a delete button that is visible on hover (although on
// a touch device JsPlumb will ensure it is always visible)
deleteButton:OVERLAY_VISIBILITY_HOVER,
overlays:[
{
// show a plain arrow at the end of each edge.
type:PlainArrowOverlay.type,
options:{
location:1,
width:10,
length:10
}
}
]
}
}
}
const renderOptions = {
// zoom content to fit on load
zoomToFit:true,
// allow user to right-click to inspect (in prod you probably want to leave this out)
consumeRightClick:false,
defaults:{
// paint a transparent outline around connectors, to make it easier to hover
// to see the delete button.
paintConnectorOutline:true,
// anchors are always on the right edge of the source and the left edge of the target
anchors:[AnchorLocations.Right, AnchorLocations.Left],
// use an orthogonal connector with a 5px corner radius
connector:{
type:OrthogonalConnector.type,
options:{
cornerRadius:5
}
}
}
}



















