Adding custom data to link on creation depending on node data

Hi,

I have nodes with a custom data property “nodeType”. I have added the custom properties “fromType” and “toType” to my linktemplate. When I create a new link between two nodes I want to populate “fromType” with the value of “nodeType” in the fromnode, and “toType” with the value of “nodeType” in the tonode. How could I accomplish this?

If you only want to do that when the user draws a new link, implement a “LinkDrawn” DiagramEvent listener that modifies the new Link, e.subject, Link.data properties the way that you want, based on the Link.fromNode and Link.toNode data properties.

I think you can find examples of “LinkDrawn” listeners.

Thank you, I was able to use that event. For anyone wondering who read this later you end up with something like this:

myDiagram.addDiagramListener(“LinkDrawn”, function(e) {
var link = e.subject;
link.data.fromType = link.fromNode.nodeType;
link.data.toType = link.toNode.nodeType;
});

(toType, fromType and nodeType being custom properties)

Did you mean to write this instead?

myDiagram.addDiagramListener("LinkDrawn", function(e) {
    var link = e.subject;
    link.data.fromType = link.fromNode.data.nodeType;
    link.data.toType = link.toNode.data.nodeType;
});

No. link.toNode.nodeType gets the custom property just fine (you can test it yourself with a console.log as well). But I have to use link.data to SET it. Maybe toNode/fromNode implicitly gets the data? I don’t know, but it works.

But there is no “nodeType” property on the Node class: Node | GoJS API

Whereas you stated that in your app there is a nodedata.nodeType property. So link.fromNode.data.nodeType should work, and link.fromNode.nodeType should not unless you have done something else to set that.

nodeType has been injected into the nodeTemplate like this:

myDiagram.nodeTemplateMap.add("CAMERA",
    $(go.Node, "Auto",
        {
            contextMenu: nodeMenu
        },
        new go.Binding("nodeType", "nodeType"),
        new go.Binding("id", "id"),
        new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
        $(go.Shape, "RoundedRectangle",
            { fill: redgrad, stroke: "black",
                portId: "", fromLinkable: true, toLinkable: true, cursor: "pointer", toEndSegmentLength: 50, fromEndSegmentLength: 40}),
        $(go.Panel, "Vertical",
            $(go.Picture, {desiredSize: new go.Size(30, 30), source: "resources/primefaces-svv/images/kamera.png"}),
            $(go.TextBlock, "CAMERA", textStyle(),
                new go.Binding("text", "text"))
        )
    ));

I can access it just fine in the example I posted above.

That might work. But you’ll get warnings about there not being any “nodeType” property on the Node.

While developing your app you are using go-debug.js and checking the console output, aren’t you?

But if you always referred to the “nodeType” property on the data, you wouldn’t have the inefficiency that comes with having that extra Binding and modifying the class signature that the JavaScript interpreter sees.

I am using go-debug.js and checking console, yes. I already got the warning you mention* before I implemented this, and I’m not directly accessing it through property anywhere else. I just gave up trying to fix it because it behaves as intended. I thought the binding was necessary to bind information to a node/link? I did the same with my linkTemplate to store fromType/toType.

*something like this:

Binding error: undefined target property: nodeType on Node#743(Kamera)

The information you want is on properties of the Node.data (or Link.data) object, so they are always accessible.

If you really want to do it, even though it’s slower and uses more memory, we can’t stop you. We just recommend that you don’t do that.

Well, it’s not that I want to do it, it’s that I thought it was necessary to bind backend data to nodes. It seems to work without the binding, so I’ll see how it goes.