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
andOverlay
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 tojtk-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 oftarget
. 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 thefilter
attribute, edges can only be dragged from the element with classconnect
.In version 5.x, the
jtk-source
andjtk-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 targetdata-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 elementThis 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.
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"
}
}
]
})