Skip to main content

UI Overview

The Toolkit maintains a clear separation between model and view: it is possible to create a Toolkit instance and manipulate its data model without actually rendering it anywhere. Of course in the real world almost every application using the Toolkit is running in a browser.

On this page we provide a basic summary of the key concepts and terms you'll come across when configuring the UI with the Toolkit.

Rendering

To visualise the contents of a Toolkit, it needs to be rendered. To do that, the Toolkit needs 3 pieces of information:

  • container Which DOM element should the Toolkit render into?
  • view How should the Toolkit map nodes/groups/edges to their visual representations?
  • renderParams What configuration should the Toolkit apply to the surface that is rendering your content?

When you render the contents of a Toolkit you get an object of type Surface. You'll see references to "surface" all through the documentation. It is the key UI component in the Toolkit, offering pan/zoom, layouts, clamping movement, backgrounds, and a whole lot more.

Library integrations

When you use a library integration such as Angular, React, Vue 2, Vue 3 or Svelte, you will not manually instruct a Toolkit to render, but rather you'll use the surface component that ships with the integration you are using, details of which can be found in the relevant docs.

What is the same, though, is that you will use the concept of view and of renderParams. Those two concepts are key UI concepts when working with the Toolkit.

Hello World

This example - from the Hello World page - illustrates a few key concepts:

Container

someElement is the container into which we want the Toolkit to render

Render params

Our renderParams in this example consist of instructing the Toolkit which layout to use, and also providing a listener for when the user clicks on whitespace in the canvas

View

Views are a big topic, and have their own page. In this example we have:

  • A base node definition, which is "abstract" in that it only declares an event listener - it does not declare a template that the Toolkit can use to render nodes of that type

  • Two concrete node definitions, which both extend the base node definition, and which provide a template to use for rendering nodes of the given type.

  • A default edge definition, declaring an arrow overlay at the tip of the edge (location 1), and instructing the Toolkit to extract label from each edge's backing data and use it as a label overlay.

  • Some UI defaults - Continuous anchors and a Blank endpoint


import { ready, newInstance, AbsoluteLayout,
BlankEndpoint, AnchorLocations, ArrowOverlay, DEFAULT } from "@jsplumbtoolkit/browser-ui"

ready(() => {

// Get a new Toolkit instance
const toolkit = newInstance()

// Get the DOM element to render into
const container = document.getElementById("container")

// Render to a Surface.
const surface = toolkit.render(container, {
layout:{
// there are several layouts that ship with the toolkit.
type:AbsoluteLayout.type,
options:{
//... if your chosen layout is configurable, options go here
}
},
// Allows us to specify edge color (and line width) in each edge's backing data
simpleEdgeStyles:true,
// Use a Continuous anchor and a blank endpoint by default.
defaults:{
anchor:AnchorLocations.Continuous,
endpoint:BlankEndpoint.type
},
// map node types and edge types to appearance and behaviour
view:{
nodes:{
// abstract parent node definition - declares a tap listener
clickable:{
events:{
tap:(p) => alert(`You clicked on node ${p.obj.id}`)
}
},
// definition for 'hello' nodes. Extends 'clickable' to get the tap listener.
hello:{
parent:"clickable",
template:'<div class="hello-node">{{label}}</div>'
},
// definition for 'world' nodes. Extends 'clickable' to get the tap listener.
world:{
parent:"clickable",
template:'<div class="world-node">{{label}}</div>'
}
},
edges:{
// a default edge definition. Declares an arrow overlay at its tip and extracts 'label' from
// edge data and displays it as a label overlay (by default at location 0.5)
[DEFAULT]:{
overlays:[
{
type:ArrowOverlay.type,
options:{
location: 1
}
}
],
label:"{{label}}"
}
}
}
})
})

tip

If you're using a library integration you won't make a direct call like this; you'll be using a component from the Toolkit's specific integration code, but you will be providing an object of the same type as shown above. We refer to this throughout the documentation as the renderParams or "render params", and these are of type SurfaceRenderOptions. Throughout the documentation you'll see us refer to "render params" - that's an object conforming to the SurfaceRenderOptions interface.

The result of that is: