Programmatic API
There is a full API available for you to manage your data model programmatically. Broadly, the operations on the data model can be broken up into three main categories:
- Adding model objects
- Deleting model objects
- Updating model objects
There are some additional operations available on groups - the addition/removal of child vertices.
Nodes
Adding nodes
There are two ways to add a node, either directly via the addNode
method, whose signature is:
addNode(data: ObjectData, eventInfo?: any): Node
for example:
toolkit.addNode({id:"1", foo:"a value", type:"someType"})
or, if you have a node factory setup on your instance, you can add a node by invoking the factory, via the addFactoryNode
method, whose signature is:
addFactoryNode(type: string, data?: ObjectData, continueCallback?: Function): void
Consider that you have a node factory that does a fetch to some endpoint, providing the type for the new node, and the endpoint responds with the data for your new node:
const toolkit = jsPlumbToolkitBrowserUIVanilla.newInstance({
nodeFactory:function(type, data, callback, evt, native) {
fetch({type:"post", body:{type}}).then(v => callback(v))
}
};
You can invoke the factory in a few ways. Firstly you can invoke the factory without supplying any data of your own:
toolkit.addFactoryNode("someType");
It is possible to also provide some seed data for the new node, which will be passed in to the node factory as data
:
toolkit.addFactoryNode("someType", { foo:"bar" });
And also you can provide a callback which will be run after the node factory has finished adding the new node:
toolkit.addFactoryNode("someType", { foo:"bar" }, (newNode) => {
// newNode is your new node.
});
Removing nodes
Nodes can be removed with the removeNode
method, whose signature is:
removeNode(node: string | Vertex): JsPlumbToolkit
for example:
toolkit.removeNode("someNodeId")
Updating nodes
To update a node, use updateNode
or updateVertex
:
updateNode(node: string | Node | ObjectData, updates?: ObjectData): void
updateVertex(vertex: string | Node | Group | Port | ObjectData, updates?: ObjectData): void
toolkit.updateNode("someNodeId", { foo:"new value"})
Groups
Adding groups
As with nodes, you can add a group directly using addGroup
, whose signature is:
addGroup(data: ObjectData, eventInfo?: any): Group
for example:
toolkit.addGroup({id:"1", foo:"a value", type:"someType"})
or you can setup a group factory and use the addFactoryGroup
method, whose signature is:
addFactoryGroup(type: string, data?: ObjectData, continueCallback?: Function): void
const toolkit = jsPlumbToolkitBrowserUIVanilla.newInstance({
groupFactory:function(type, data, callback, evt, native) {
fetch({type:"post", body:{type}}).then(v => callback(v))
}
};
You can call addFactoryGroup
just by supplying the desired type for your new group:
toolkit.addFactoryGroup("someType");
Or by supplying type and initial data:
toolkit.addFactoryGroup("someType", { foo:"bar" })
Or by supply type, data and a callback:
toolkit.addFactoryGroup("someType", { foo:"bar" }, (newGroup) => {
// newGroup is your new group
});
Removing groups
Groups can be removed with the removeGroup
method:
removeGroup(group: string | Group, removeChildren?: boolean):void
Note the removeChildren
option to this method. By default when you remove a group its child vertices are orphaned, or if the group is itself a child of some other groups its child vertices are added to the group's parent.
This will remove a group and leave its child vertices in the dataset:
toolkit.removeGroup("someNodeId")
This will remove a group and its child vertices (and if any of those child vertices is a group, its children will be removed etc):
toolkit.removeGroup("someNodeId", true)
Updating groups
To update a group, use updateGroup
(or updateVertex
as shown above in the removing nodes section):
toolkit.updateGroup("someNodeId", { foo:"new value"})
Ports
Adding ports
Ports reside on nodes or groups, and so to add a port you have to supply the vertex you wish to add the port to. To add a port directly to a node or group you use addPort
:
addPort(vertex: string | Node | Group, data: ObjectData): Port
So, for instance:
const node = toolkit.addNode({id:"one", type:"someType"})
const port = toolkit.addPort(node, {id:"p1", type:"somePortType"})
The equivalent to the addFactoryNode
and addFactoryGroup
method for ports is:
addNewPort(obj: string | Node | Group, type: string, portData?: ObjectData)
addNewPort
will invoke the Toolkit's port factory and then call addPort
with the port factory's result.
As an example, this is the port factory from an early version of our Schema Builder starter app, in which table columns are represented as ports on table nodes:
const toolkit = new jsPlumbBrowserUIVanilla({
portFactory:(node, type, data, callback) => {
let column = {
id:data.columnName,
name:data.columnName[0].toUpperCase() + data.columnName.slice(1),
datatype:"varchar",
type:"column"
};
// add to node's data. we have to do this manually. the Toolkit does not know our internal
// data structure.
node.data.columns.push(column);
// handoff the new column.
callback(column);
}
})
const node = toolkit.addNode({id:"one", type:"table", columns:[]})
// this call will invoke the portFactory declared above:
toolkit.addNewPort(node, "column", (column) => {
// `column` is your new port, and has been added to node one.
})
The addPort
and addNewPort
methods discussed here will add ports to model objects, but they will not necessarily update the underlying JSON dataset. It is important to be across the concepts discussed regarding the synchronization of port data
Removing ports
Use the removePort
method to remove a port from the dataset:
removePort(vertexOrId: string | Node | Group | Port, portId?: string): boolean
This method can be called in a few ways.
With full port id
You can provide the full port id in dotted notation, from which the Toolkit will resolve the node/group and the port:
toolkit.removePort("someNode.somePortId")
With a port object
You can provide a Port
model object:
const port = toolkit.addPort(someNode, { id:"portId", foo:"foo"})
...
toolkit.removePort(port)
With a node/group and port id
Lastly, you can provide the node/group that is the port's parent, and the port id:
toolkit.removePort(someNode, "portId")
We again refer you to the documenation regarding the synchronization of port data. Removing ports using these methods will remove the ports from the model, but to ensure the data is removed from the dataset you will need to have configured the Toolkit to recognize where your port data is stored on your nodes/groups.
Updating ports
To update a port, use the updatePort
method, whose signature is:
updatePort(port: Port | string, updates?: ObjectData): void
You can call this method with either a full port id:
toolkit.updatePort("someNode.somePortId", {field:"updatedValue"})
or with a Port
model object:
const port = toolkit.addPort(someNode, { id:"portId", field:"originalValue"})
toolkit.updatePort(port, {field:"updatedValue"})
Edges
Adding edges
You can add an edge programmatically to the dataset via the addEdge
method:
export interface AddEdgeOptions {
source:Vertex|string
target:Vertex|string
geometry?:any
data?:any
cost?:number
directed?:boolean
}
addEdge(params: AddEdgeOptions): Edge
Adding an edge is slightly different to adding vertices, in that the backing data for an edge should be provided in a data
object inside the payload you pass to this method. With nodes, groups and ports the backing data is at the top level.
The source
and target
you pass to this method can either be objects of type Vertex
(Node
, Group
or Port
), or they can be the ID of some vertex, in the case of ports this being a fully qualified port id in dotted notation. Some examples:
Here we add an edge from some Node
to a port which we specify by id. We also supply some data for the edge - in this case, a label. The resulting edge has an ID that the Toolkit assigns:
const edge = toolkit.addEdge({source:someNode, target:"someOtherNode.somePortId", data:{label:"My Edge Label"}})
Here we add an edge between two vertices specified by id. We also supply some data for the edge - in this case, the edge's ID, and also a label:
const edge = toolkit.addEdge({
source:"node1",
target:"node2",
data:{
label:"Label",
id:"edgeId"
}
})
Removing edges
You can remove an edge via removeEdge
, whose signature is:
removeEdge(edge: string | Edge):JsPlumbToolkit
Edges can be removed by supplying the edge ID (see the example above for how to set an edge id):
toolkit.removeEdge("edgeId")
or by supplying an Edge
model object:
const edge = toolkit.addEdge({source:someNode, target:"someOtherNode.somePortId", data:{label:"My Edge Label"}})
...
toolkit.removeEdge(edge)
Updating edges
Edges can be updated with the updateEdge
method, whose signature is:
updateEdge(obj: Edge | string, updates?: ObjectData): void
As with removeEdge
, the edge in question can be identified by its id or by an Edge
object. Here we update our edge from before via its id with a new label:
toolkit.updateEdge("edgeId", {label:"New Label"})
Undo/redo and transactions
All of the methods discussed on this page are connected to the underlying undo/redo stack, and run inside a transaction.
Certain methods can cause a cascade of other operations on the data model:
- removal of a vertex causes the removal of all edges to that vertex and to any ports on the vertex
- removal of a group with
removeChildren:true
will cause the removal of any child vertices, and edges connected to them
Since each method runs inside a transaction, calling undo()
on a Toolkit instance will result in the rollback of every operation executed on the data model in response to some specific method call. Calling redo()
will result in the re-application of every operation executed by the original method call.
Events
The various add, update and remove methods will cause a corresponding event to be fired:
Method | Event | Payload |
---|---|---|
addNode | EVENT_NODE_ADDED | {data:ObjectData, node:Node, parentGroup?:Group} |
updateNode | EVENT_NODE_UPDATED | {updates:ObjectData, vertex:Node |
removeNode | EVENT_NODE_REMOVED | {node: Node, nodeId: string, edges: Array<Edge>, parentGroup?:Group } |
addGroup | EVENT_GROUP_ADDED | {data:ObjectData, node:Node, parentGroup?:Group} |
updateGroup | EVENT_GROUP_UPDATED | {updates:ObjectData, vertex:Node |
removeGroup | EVENT_GROUP_REMOVED | {node: Group, groupId: string, edges: Array<Edge>, parentGroup?:Group } |
addPort | EVENT_PORT_ADDED | {data:ObjectData, vertex:Vertex, port:Port} |
updatePort | EVENT_PORT_UPDATED | {updates:ObjectData, vertex:Node |
removePort | EVENT_NODE_REMOVED | {vertex: Vertex, port:Port, edges: Array<Edge> } |
addEdge | EVENT_EDGE_ADDED | {edge:Edge} |
updateEdge | EVENT_EDGE_UPDATED | {updates:ObjectData, edge:Edge, originalData:ObjectData} |
removeEdge | EVENT_EDGE_REMOVED | {edge: Edge } |