Skip to main content

Migration from 2.x to 5.x

There are a number of breaking changes between 5.x and 2.x, which fall broadly into one of 3 categories - Packaging, Events and Rendering.

Packaging

The Toolkit is now delivered as a set of packages under the scope @jsplumbtoolkit, and the Community edition is now delivered as a set of packages under the scope @jsplumb. The first thing you'll need to do is to update your package references.

If you do not use a bundler we'd love to hear from you, as we realise that splitting up a library into a number of packages introduces certain complications in terms of knowing what to import. Drop us a line at hello@jsplumbtoolkit.com and we can discuss.

Read more about available packages here


Events

The format of event names across the Toolkit has been standardised and many events have changed. The general form in 5.x is object:action, for instance edge:added, edge:updated, which in 2.x would have been edgeAdded and edgeUpdated respectively.

All the events fired by the Toolkit and the Surface are listed on the events page.


Rendering

The core of the renderer exists in a separate package - @jsplumbtoolkit/browser-ui - from its specific implementations. Rather than import this package, users now need to import a specific package appropriate for either the library integration they are using, or for vanilla Toolkit (ie using the Toolkit's own template renderer). Available packages are:

- `@jsplumbtoolkit/browser-ui-vanilla`
- `@jsplumbtoolkit/browser-ui-angular`
- `@jsplumbtoolkit/browser-ui-react`
- `@jsplumbtoolkit/browser-ui-vue2`
- `@jsplumbtoolkit/browser-ui-vue3`
  • Changes have been made to the syntax of things like Anchor, Connector, Endpoint and Overlay definitions, to standardise them and also to make them interoperate more nicely with Typescript's type inferencing. There is a now a standard syntax used for all of these types, and it also the standard used for specifying a layout and plugins for a Surface. For further information on this new syntax, see this section in the rendering migration page. For information on views in general in 5.x, see this page.
  • The jtk-port element has been renamed to jtk-endpoint. Read more Read more here

The render call

When using vanilla Toolkit (ie. no library integration) you will at some point have called render on a Toolkit instance to setup a Surface:

var tk = jsPlumbToolkit.newInstance();
var surface = tk.render({
container:someElement,
etc
})

In version 5.x, container is now passed as the first argument to render:

const tk = jsPlumbToolkitBrowserUIVanilla.newInstance()
const surface = tk.render(someElement, {
etc
})

Connector, Anchor, Endpoint and Overlay Specs

The syntax of connector, anchor, endpoint and overlay specifications has changed in 5.x. Consider this view from 2.x:

view:{
edges:{
default:{
connector:[ "Bezier", { curviness:50 }],
endpoint:[ "Dot", { radius:10 }],
anchor:[ "Continuous", { faces:["top", "bottom"] }],
overlays:[
[ "Label", { label:"Foo" }]
]
}
}
}

In 5.x you would write the same thing as follows:

view:{
edges:{
default:{
connector:{ type:"Bezier", options:{ curviness:50 } },
endpoint:{ type:"Dot", options:{ radius:10 } },
anchor:{ type:"Continuous", options:{ faces:["top", "bottom"] }},
overlays:[
{ type:"Label", options:{ label:"Foo" }}
]
}
}
}

So the general format for any of these specifications is:

{
type:string,
options?:Record<string, any>
}

View Options

The specific interface for a view now is SurfaceViewOptions from @jsplumbtoolkit/browser-ui.

Template Ids

One change you'll want to be aware of if you're a user of vanilla Toolkit, is that template, which previously indicated the ID of a template to use to render some node/group, is now used to indicate the content of the template itself, and templateId can be used where you'd use template in 2.x. For example if you had this:

2.x
{
view:{
nodes:{
someNode:{
template:"someNodeTemplate"
}
}
},
templates:{
someNodeTemplate:'<div><h1>${id}</h1></div'
}
}

You can now do one of two things - either change template to templateId:

5.x
{
view:{
nodes:{
someNode:{
templateId:"someNodeTemplate"
}
}
},
templates:{
someNodeTemplate:'<div><h1>${id}</h1></div'
}
}

..or you can now simply supply the template directly in the node mapping:

{
view:{
nodes:{
someNode:{
template:'<div><h1>${id}</h1></div'
}
}
}
}

Source and Target elements

One of the key pieces of functionality in version 2.x of the Toolkit is the ability to configure connectivity via jtk-source and jtk-target elements in your templates. For example, this is the template for the Action node type in the Flowchart builder demonstration:

<div style="left:${left}px;top:${top}px;width:${w}px;height:${h}px;" class="flowchart-object flowchart-action">
<div style="position:relative">
<svg:svg width="${w}" height="${h}">
<svg:rect x="10" y="10" width="${w-20}" height="${h-20}"/>
<svg:text text-anchor="middle" x="${w/2}" y="${h/2}" dominant-baseline="central">${text}</svg:text>
</svg:svg>
</div>
<div class="node-edit node-action"/>
<div class="node-delete node-action delete"/>
<div class="drag-start connect"></div>
<jtk-target port-type="target"/>
<jtk-source port-type="source" filter=".connect"/>
</div>

Here, we configure connectivity with two elements:

  • <jtk-target port-type="target"/> Instructs the toolkit that this DOM element is an edge target, and that when an edge is connected to this element the Toolkit should use a port type of target. The type of port has a bearing, through your view, on the appearance and behaviour of its endpoint.

  • <jtk-source port-type="source" filter=".connect"/> Instructs the toolkit that this DOM element is an edge source, and that, via the filter attribute, edges can only be dragged from the element with class connect.

    In version 5.x, the jtk-source and jtk-target elements do not exist, and this template is as follows:

    <div style="left:${left}px;top:${top}px;width:${w}px;height:${h}px;" class="flowchart-object flowchart-action" data-jtk-target="true" data-jtk-port-type="target">
    <div style="position:relative">
    <svg:svg width="${w}" height="${h}">
    <svg:rect x="10" y="10" width="${w-20}" height="${h-20}"/>
    <svg:text text-anchor="middle" x="${w/2}" y="${h/2}" dominant-baseline="central">${text}</svg:text>
    </svg:svg>
    </div>
    <div class="node-edit node-action"/>
    <div class="node-delete node-action delete"/>
    <div class="drag-start connect" data-jtk-source="true" data-jtk-port-type="source"></div>
    </div>

    The key differences to note are:

  • instead of a <jtk-target..> element, we've marked up the root element with two attributes:

    • data-jtk-target="true" Indicates that the element on which the attribute is set is an edge target
    • data-jtk-port-type="target" Provides the port type to use when an edge is connected to this element as a target
  • instead of a <jtk-source..> element, we've marked up the specific part of the template that we want to use as an edge source with two attributes:

    - `data-jtk-source="true"` Indicates that the element on which the attribute is set is an edge source
    - `data-jtk-port-type="source"` Provides the port type to use when an edge is dragged from this element

    This arrangement brings a number of benefits over how connectivity in 2.x works:

  • you can have multiple places on a specific vertex element that act as edge sources/targets, and each of those can mandate a different set of port parameters

  • the Toolkit can use delegated event handlers, which reduces memory consumption

  • the Toolkit automatically adds any element marked as data-jtk-source="true" to the list of elements that act as the drag filter for the given vertex. Previously, setting this up was a manual operation.

    For further reading, see this page. There are several more attributes you can use than just the ones shown here - there is no regression in terms of the capabilities of this architecture when compared with the capabilities in 2.x.

    TOP

EditableFlowchart connector

In 5.x this connector has been renamed to Orthogonal and is delivered in a separate package - @jsplumbtoolkit/connector-orthogonal. The format of the geometry for this connector type has also changed:

2.x - EditableFlowchart geometry
{
"segments": [
[
300,
400
],
[
350,
400
],
[
400,
400
]
],
"source": [
300,
350,
0.5,
1,
0,
1
],
"target": [
450,
400,
0,
0.5,
-1,
0
]
}
5.x - Orthogonal geometry
{
"segments": [
{
x:300,
y:400
},
{
x:350,
y:400
},
{
x:400,
y:400
}
],
"source": {
curX:300,
curY:350,
x:0.5,
y:1,
ox:0,
oy:1
},
"target": {
curX:450,
curY:400,
x:0,
y:0.5,
ox:-1,
oy:0
}
}

Port elements

In version 2.x you could use a jtk-port element to instruct the Toolkit to add an Endpoint to the UI:

<div class="foo">
<h1>${name}</h1>
<jtk-port port-id="aPort" port-type="aPortType"></jtk-port>
</div>

In 5.x this element has been renamed to jtk-endpoint:

<div class="foo">
<h1>${name}</h1>
<jtk-endpoint data-jtk-port="aPort" data-jtk-port-type="aPortType"></jtk-endpoint>
</div>

This was done mainly to reduce confusion, since ports are a data model concept and this element is a UI decision.

Plugins

In 2.x a number of utilities such as the miniview, the lasso tool, and the nudge buttons, were shipped as part of the Surface itself. Not every application uses all of these tools, though, so in 5.x we've introduced a plugin architecture for the Surface, and we've extracted these tools, as well as a couple of other things, to plugins. The plugins documentation is a good place to read about these, but for the purposes of migration we provide a brief overview here.

Consider this miniview declaration in 2.x:

var surface = myToolkit.render({
container:someElement,
miniview:{
container:miniviewElement
}
})

in 5.x you'd achieve the same thing like this:

import { MiniviewPlugin } from "@jsplumbtoolkit/browser-ui-plugin-miniview"

var surface = myToolkit.render(someElement, {
plugins:[
{
type: MiniviewPlugin.type,
options:{
container:miniviewElement
}
}
]
})

Every plugin exposes a static type member. Here's another example, with both a miniview and a lasso, with a lasso filter defined, in 2.x:

var surface = myToolkit.render({
container:someElement,
miniview:{
container:miniviewElement
},
lassoFilter:".someClass, .someOtherClass"
})

and in 5.x:


import { MiniviewPlugin } from "@jsplumbtoolkit/browser-ui-plugin-miniview"
import { LassoPlugin } from "@jsplumbtoolkit/browser-ui-plugin-lasso"

var surface = myToolkit.render(someElement, {
plugins:[
{
type: MiniviewPlugin.type,
options:{
container:miniviewElement
}
},
{
type: LassoPlugin.type,
options:{
filter:".someClass, .someOtherClass"
}
}
]
})