- Imports
- Setup
- Bootstrap
- Imports
- jsPlumbToolkitVue2 module
- Components
- jsplumb-toolkit
- jsplumb-miniview
- SurfaceDrop mixin
- BaseNodeComponent
- BaseGroupComponent
- Rendering Nodes and Groups
- Rendering Ports
- DragDrop Mixin
- Inserting a node between two existing nodes on drop
Vue 2 Integration
The jsPlumb Toolkit has several components to assist you in integrating with Vue 2 in dist/jsplumbtoolkit-vue2.tgz
.
You may also like to read the documentation for the Vue2 Flowchart Builder demonstration
You need to include the jsPlumb Toolkit and the jsPlumb Toolkit Vue 2 adapter. Since the Toolkit edition is not open source, if you need to include it as an import in package.json, you can use (from NPM 3+) a local import:
ES6 Module
"dependencies": {
...
"jsplumbtoolkit":"file:./somewhere/jsplumbtoolkit.tgz",
"jsplumbtoolkit-vue2":"file:./somewhere/jsplumbtoolkit-vue2.tgz"
...
},
From 2.1.0 the Vue2 components are shipped with precompiled templates, meaning you need to import the Toolkit in your Vue bootstrap code. For instance, this is the bootstrap routine from the Vue Flowchart demo that ships with the Toolkit:
import Vue from 'vue'
import App from './App.vue'
import { JsPlumbToolkitVue2Plugin } from 'jsplumbtoolkit-vue2'; // <---- import the Toolkit Vue 2 plugin
Vue.config.productionTip = false
require('@/assets/css/jsplumbtoolkit.css');
require('@/assets/css/jsplumbtoolkit-demo-support.css');
require('@/assets/css/jsplumbtoolkit-editable-connectors.css');
require('@/assets/css/app.css');
Vue.use(JsPlumbToolkitVue2Plugin); // <-- instruct Vue to load the Toolkit plugin
new Vue({ render: h => h(App) }).$mount('#app')
The jsPlumbToolkitVue2
module coordinates the various Vue components offered by the Toolkit
Most of the integration work between the Toolkit and Vue is taken care of by the components the Toolkit offers (discussions of which follow below) via interaction with "private" methods on the jsPlumbToolkitVue2
module. There is one public method on the module that you may find yourself using, though:
- getSurface(id:string, callback:(s:Surface)=>any):void
Retrieves the surface with the given ID. We will update this to return a Promise at some stage. It is asynchronous because it is feasible that a call could be made to this method prior to the Surface having been created.
The Toolkit offers 2 components and 3 mixins:
This component provides an instance of the Toolkit and a Surface widget to render the contents.
Example
<jsplumb-toolkit id="toolkit" surface-id="surfaceId" v-bind:render-params="anObjectReference"
v-bind:toolkit-params="anObjectReference" v-bind:view="anObjectReference">
</jsplumb-toolkit>
Attributes
All attributes are optional. Note that Vue prefers "kebab case" for attribute names, even if the actual property is camel case on the component (and of course Javascript does not like kebab case for property names).
id
Unique ID for the Toolkit instance. Can be used to retrieve a Toolkit instance from the jsPlumbToolkitVue2 module.surface-id
Unique ID for the Surface widget. Required if you wish to attach a Miniview or a Palette. Also useful if you wish to interact with a Surface, to perform operations such as zooming, centering on content, etc.render-params
Parameters to pass in to the constructor of the Surface widget. Note here we use thev-bind:
prefix to tell Vue that the object we are injecting is in the Vue instance's model.toolkit-params
Parameters to pass in to the constructor of the Toolkit instance. Note again the use ofv-bind:
in our example above.view
View parameters. Views are discussed here.
This is a component that provides a Miniview that can be attached to some Surface.
Example
Attributes
surface-id
ID for the Surface widget to which to attach the Miniview.
This mixin is a wrapper around the Drop Manager, which offers the ability to drop onto edges, nodes and the canvas itself
Installation
This mixin is supplied in a separate package, as it has a dependency on the Toolkit's underlying Drop Manager.
"devDependencies":{
...
"jsplumbtoolkit-drop":"file:./somewhere/jsplumbtoolkit-drop.tgz",
"jsplumbtoolkit-vue2-drop":"file:./somewhere/jsplumbtoolkit-vue2-drop.tgz"
}
Example
This is an example of a component that uses the SurfaceDrop mixin. We show, in the onCanvasDrop
method, an example of how this mixin can be used to replace the previous Palette mixin. Note, though, the onEdgeDrop
and onDrop
methods: these are, respectively, called when an element is dragged on an Edge or a Node/Group.
<template>
<div class="sidebar node-palette">
<div class="sidebar-item" :data-node-type="entry.type" title="Drag to add new" v-for="entry in data" :key="entry.type">
<i :class="entry.icon"></i>{{entry.label}}
</div>
</div>
</template>
<script>
import { SurfaceDrop } from 'jsplumbtoolkit-vue2-drop';
export default {
mixins:[ SurfaceDrop ],
data:function() {
return {
data:[
{ icon:"icon-tablet", label:"Question", type:"question" },
{ icon:"icon-eye-open", label:"Action", type:"action" },
{ type:"output", icon:"icon-eye-open", label:"Output" }
]
};
}
}
</script>
Note that this component itself doesn't declare any props
, and you are free to provide any template you wish to render the component's data
. The underlying DragDrop
mixin's props
are:
- surfaceId:string Required. The ID of the Surface to which to attach the Drop Manager.
- selector:string Required. A CSS3 selector instructing the Toolkit how to identify which elements in the component represent draggable node types.
- dataGenerator:(el:HTMLElement) => T Optional. A function that can return a data object representing an element which is being dragged. This function is called as soon as an element starts to be dragged.
- allowDropOnGroup:boolean Optional, defaults to true. If true, then elements can be dropped onto nodes/groups, and in the event that occurs, the
onDrop
method will be called. - allowDropOnCanvas:boolean Optional, defaults to true. When an element is dropped on the canvas whitespace, it is added to the dataset and rendered.
- allowDropOnEdge:boolean Optional, defaults to true. If true, then elements can be dropped onto edges, and in the event that an element is dropped on an edge, a new node/group is added and inserted between the source and target of the original edge, and the original edge is discarded..
- typeGenerator:(data:T) => string Optional. A function that can return the correct type for some data object representing an element being dragged. By default the Toolkit will use the
type
member of the data object. - groupIdentifier:(d: T, el: HTMLElement) => boolean Optional. By default, the toolkit looks for a
jtk-is-group
attribute on an element being dragged. If found, with a value of"true"
, then the Toolkit assumes a group is being dragged. You can supply your own function to make this decision.
This mixin should be included in any component you will use to render a node (see below for discussion of this). Several helper methods are exposed by this mixin:
- getNode() Gets the underlying Toolkit node that the component is rendering
- removeNode() Instructs the Toolkit to remove the node that the component is rendering. This will of course result in the destruction of the component.
- getToolkit() Gets the underlying Toolkit instance for the node the component is rendering.
- updateNode(data:any) Updates the underlying node that the component is rendering.
Nodes rendered with this mixin are fully reactive: calls to updateNode
will result in a repaint of the component with no further effort involved on your part.
This mixin should be included in any component you will use to render a group (see below for discussion of this). Several helper methods are exposed by this mixin:
- getGroup() Gets the underlying Toolkit group that the component is rendering
- removeGroup(removeChildNodes?:boolean) Instructs the Toolkit to remove the group that the component is rendering, and possibly all of the child nodes of the group too. This will of course result in the destruction of the component.
- getToolkit() Gets the underlying Toolkit instance for the group the component is rendering.
- updateGroup(data:any) Updates the underlying group that the component is rendering.
Groups rendered with this mixin are fully reactive: calls to updateGroup
will result in a repaint of the component with no further effort involved on your part.
To render nodes and groups you have two options:
- use the Toolkit's default template renderer, Knockle
- use a Vue component for each node/group type
Using a Vue component is of course far more appealing, and we'll discuss that first. It's pretty straightforward: you create a component, import it into the code that's handling your Toolkit instance, and then map it via the view. Imagine you make this component inside MyNode.vue
:
<template>
<div>
<h1>{{obj.label}}</h1>
<button v-on:click="clicked()">CLICK ME</button>
</div>
</template>
<script>
import { BaseNodeComponent } from "jsplumbtoolkitvue2";
export default {
mixins:[ BaseNodeComponent ],
methods:{
clicked:function() {
alert(this.getNode().data.label);
}
}
}
</script>
And you make this component, to manage an instance of the Toolkit:
<template>
<jsplumb-toolkit
ref="toolkitComponent"
url="flowchart-1.json"
v-bind:render-params="renderParams"
v-bind:view="view"
id="toolkit"
surface-id="surface"
v-bind:toolkit-params="toolkitParams">
</jsplumb-toolkit>
</template>
<script>
import MyNode from './MyNode.vue';
export default {
name: 'jsp-toolkit',
props:["surfaceId"],
data:() => {
renderParams:{ ... },
view:{
nodes:{
default:{
component:MyNode
}
}
}
}
}
</script>
MyNode
is mapped to the component
used to render nodes of type "default" (which for the Toolkit means any node). The jsplumb-toolkit
declaration in the template is the one from the [demo-vue2](Vue2 Flowchart Demonstration), which is a good place to look to get a feel for how a whole application can be built using the Toolkit.
The Angular and React integrations that ship with the Toolkit offer specific support for rendering ports as well as node and groups. The initial release of the Toolkit's upgraded Vue integration does not yet offer this, but we're working on it for our next release. This functionality is of specific use if you are building an application like the [demo-angular-database-visualiser](Database Visualiser).
NOTE Unless you need to respond to a drop on a node, the Surface Drop Manager provides a more simple way of configuring drag/drop of new items. This section is still valid, but it's not the fastest way of adding the functionality.
This mixin is a wrapper around the Drop Manager, which offers the ability to drop onto edges, nodes and the canvas itself, and is a replacement for the original Palette mechanism. The Palette still exists, as does its Vue wrapper, but will be deprecated in an upcoming release and then eventually removed.
Installation
This mixin is supplied in a separate package, as it has a dependency on the Toolkit's underlying Drop Manager.
"devDependencies":{
...
"jsplumbtoolkit-drop":"file:./somewhere/jsplumbtoolkit-drop.tgz",
"jsplumbtoolkit-vue2-drop":"file:./somewhere/jsplumbtoolkit-vue2-drop.tgz"
}
Example
This is an example of a component that uses the DragDrop mixin. We show, in the onCanvasDrop
method, an example of how this mixin can be used to replace the previous Palette mixin. Note, though, the onEdgeDrop
and onDrop
methods: these are, respectively, called when an element is dragged on an Edge or a Node/Group.
<template>
<div class="sidebar node-palette">
<div class="sidebar-item" :data-node-type="entry.type" title="Drag to add new" v-for="entry in data" :key="entry.type">
<i :class="entry.icon"></i>{{entry.label}}
</div>
</div>
</template>
<script>
import { DragDrop } from 'jsplumbtoolkit-vue2-drop';
export default {
mixins:[ DragDrop ],
data:function() {
return {
data:[
{ icon:"icon-tablet", label:"Question", type:"question" },
{ icon:"icon-eye-open", label:"Action", type:"action" },
{ type:"output", icon:"icon-eye-open", label:"Output" }
]
};
},
methods:{
onCanvasDrop:function(surface:Surface, data:any, positionOnSurface:[number, number]) {
surface.getToolkit().addFactoryNode(data.type, {
left:positionOnSurface.left,
top:positionOnSurface.top,
foo:data.foo
});
},
onEdgeDrop:function(surface:Surface, data:any, edge:Edge,
positionOnSurface:[number, number],
draggedElement:HTMLElement, evt:Event,
pageLocation:{left:number, top:number}) {
...
},
onDrop:function(surface:Surface, data:any, target:Node|Group,
positionOnSurface:[number, number],
draggedElement:HTMLElement,
event:Event) {
...
}
}
}
</script>
Note that this component itself doesn't declare any props
, and you are free to provide any template you wish to render the component's data
. The underlying DragDrop
mixin's props
are:
- surfaceId Required. The ID of the Surface to which to attach the Drop Manager.
- selector Required. A CSS3 selector instructing the Toolkit how to identify which elements in the component represent draggable node types.
- dataGenerator Optional. A function that can return a data object representing an element which is being dragged. This function is called as soon as an element starts to be dragged.
- allowDropOnNodesAndGroups Optional, defaults to false. If true, then elements can be dropped onto nodes/groups, and in the event that occurs, the
onDrop
method will be called. - allowDropOnCanvas Optional, defaults to true, which mimics the behaviour of the original Palette. When an element is dropped on the canvas whitespace, the
onCanvasDrop
method will be called. - allowDropOnEdges Optional, defaults to false. If true, then elements can be dropped onto edges, and in the event that occurs, the
onEdgeDrop
method will be called.
Each of the methods
shown are optional, but you will of course want to provide an implementation of at least one of them:
- onCanvasDrop Called when an element is dropped on the canvas whitespace.
- onEdgeDrop Called when an element is dropped on an edge.
- onDrop Called when an element is dropped on a node or group.
This is a use case we are asked about fairly regularly. A discussion of this can be found in the Drop Manager documentation.