Tomasz Swistak

|
|

Simple GoJS Application. Setting and Editing Edges

In the last post I showed you how to get started with a GoJS application. I explained how to create a diagram and how to present data using it. Let’s go a step further.

Figure 1. Diagram with three templates for nodes

While our diagram is starting to look better, there are a few issues that stick out. First – it can’t be edited (the only thing you can do is move the nodes around and clone them using the CTRL key), and second – we might want the edges to be drawn between specific points of the nodes. This is particularly visible in the objects that were created from the SVG paths – the best thing would be to set the entry from the left and set the exit from the right. But to do this, we first need to define the ports.

Ports are parts of nodes with only one function – setting the edges in relation to the rest of the object. They may consist of elements of nodes that already exist (even an entire node), or they can be new elements created especially for this purpose. Ports are defined by setting a value for the portId field. There are some other things we can do, for example: define whether we can create new links from the port (fromLinkable field) and whether we can attach new links to it (toLinkable). For the purposes of this example, the ports will be defined as visible shapes, but they can be any objects (including invisible ones).

In case of first node template (black circle), we want to put the port right in the middle. In order to make it clear that this is where the edges go, we will change the color of the circle and set a fixed size for it. We’ll also configure it to make it possible to create connections from this port in both directions. Here’s how we’ll define the shape in this case:

Listing 1. Definition of the shape expanded with a port

$(go.Node, ‘Auto’,
$(go.Shape,
‘Circle’, {
width: 100,
height: 100,
fill: ‘white’
}),
$(go.Shape,
‘Rectangle’, {
portId: ”,
width: 20,
height: 20,
fill: ‘black’,
fromLinkable: true,
toLinkable: true
}))

view rawdiagram.js hosted with ❤ by GitHub

Like I already mentioned, it’s important for the portId field to have a set value. However, this value can be an empty string. If we assign an empty string, this port will be the default port.

For the second node template (SVG path), we want to define the port on its left and right side. This can be done in two ways: by changing the arrangement of elements to Horizontal and setting the shapes in the order of port-main shape-port, or by changing to Spot, then setting the ports to the Left and Right positions with the main shape in Center. The second way is more flexible, so it’s the one we will use. On the left side, we will insert the same rectangle as on the first shape and setting it so that you can only link to it. On the right side, we will insert a rectangle from which we can only lead the edges. In order to distinguish them, we should give them different identifiers than an empty string (e.g., entry and exit). Here’s what this definition looks like:

Listing 2. Definition of the shape expanded with two ports

$(go.Node,
‘Spot’,
$(go.Shape, {
// …
}),
$(go.Shape,
‘Rectangle’, {
portId: ‘entry’,
width: 20,
height: 20,
fill: ‘black’,
alignment: go.Spot.Left,
fromLinkable: false,
toLinkable: true
}),
$(go.Shape,
‘Rectangle’, {
portId: ‘exit’,
width: 20,
height: 20,
fill: ‘black’,
alignment: go.Spot.Right,
fromLinkable: true,
toLinkable: false
}))

view rawdiagram.js hosted with ❤ by GitHub

For the third template (two rectangles), let’s modify only the square on the top. We’ll make it a port by adding a portId with an empty string, and we’ll set fromLinkable and toLinkable to true. After creating the ports, here’s what the diagram should look like:

Figure 2. Diagram with preliminary configuration of the ports

As the figure above shows us, the ports work perfectly in the case of the first and third category, but they don’t work for the second one. The same thing happens when it comes to drawing links. Drawing between the first and third category is no problem, but with the second category the edges jump out of the ports. There are two reasons why this happens. First, we haven’t defined in the link model which ports the connections should occur between. Second, we haven’t set in the model how to store connections between ports. So let’s go back to initDiagram and the definition of the model. We need to add two fields to GraphLinksModellinkFromPortIdProperty and linkToPortIdProperty. These determine how we define the ports used in the model. Additionally, we should define in linkDataArray how the edges for nodes 2 and 3 (those belonging to the second category) will be done. Here’s what these changes should look like:

Listing 3. Changes in the model allowing for the use of ports

diagram.model = $(go.GraphLinksModel, {
linkFromPortIdProperty: ‘fromPort’,
linkToPortIdProperty: ‘toPort’,
nodeDataArray: [
// …
],
linkDataArray: [
{from: 1, to: 2, toPort: ‘entry’},
{from: 2, to: 3, fromPort: ‘exit’, toPort: ‘entry’},
{from: 1, to: 3, toPort: ‘entry’},
{from: 3, to: 4, fromPort: ‘exit’}
]
});

view rawdiagram.js hosted with ❤ by GitHub

Now here’s what the edges on the diagram should look like:

Figure 3. Diagram after proper configuration of the ports

In the next post we’ll put the finishing touches on this diagram. Follow us on Facebook for notifications.

This post was also published on ITNEXT. 

You can check the result of the tutorial here: