Linking simple objects

I’m currently evaluating GoJS for a client and have been following the samples to create a doubleTreeLayout, which is working exactly as we need it to.

I’ve also been able to create another node to include additional text, but I can’t for the life of me work out how to link that to the root of the doubleTreeLayout.

Here’s the relevant part of my code (which is based heavily on the sample)

doubleTreeLayout: function (diagram) {
            // Within this function override the definition of '$' from jQuery:
            var $ = go.GraphObject.make;  // for conciseness in defining templates
            diagram.startTransaction("Double Tree Layout");

            // split the nodes and links into two Sets, depending on direction
            var leftParts = new go.Set(go.Part);
            var rightParts = new go.Set(go.Part);
            bowtie.separatePartsByLayout(diagram, leftParts, rightParts);
            // but the ROOT node will be in both collections

            // create and perform two TreeLayouts, one in each direction,
            // without moving the ROOT node, on the different subsets of nodes and links
            var layout1 =
                $(go.TreeLayout,
                    {
                        angle: 180,
                        arrangement: go.TreeLayout.ArrangementFixedRoots,
                        setsPortSpot: false
                    });

            var layout2 =
                $(go.TreeLayout,
                    {
                        angle: 0,
                        arrangement: go.TreeLayout.ArrangementFixedRoots,
                        setsPortSpot: false
                    });

            layout1.doLayout(leftParts);
            layout2.doLayout(rightParts);

            var leftPoint = parseInt(((diagram.findNodeForKey("Root").actualBounds.width - 145) /2));
            var scenarioDisplay = $(go.Node, "Auto",
                {
                    position: new go.Point(leftPoint, -100)
                },
                $(go.Shape, "RoundedRectangle", {
                    fill: "yellow"
                }),
                $(go.TextBlock, scenario, {
                    margin: 5,
                    width: 150,
                    wrap: go.TextBlock.WrapFit, textAlign: "center"
                })
            );

            diagram.add(scenarioDisplay);

            diagram.commitTransaction("Double Tree Layout");
        },

It looks like I should be able to link these two things together, but I have no idea how to add an ID (key?) to the scenarioDisplay so that I can then join the two components together - all the link examples seem to assume that you’re using a template and wanting to link two ‘identical’ things together.

Any assistance much appreciated.

The normal way to add a node is to add a new node data object to the model by calling Model.addNodeData. If you want to have drastically different kinds of nodes, especially when the visual structure of the nodes wants to be different, you can use multiple templates. http://gojs.net/latest/intro/templateMaps.html Template Maps are used in many of the samples.

But you don’t have to add a node via the model with a template and its bindings. What you are doing should be feasible, but in this case I think it’s more work than going the route of adding to the model. I think you’re just missing creating a new Link, setting its Link.fromNode and Link.toNode properties, and then adding the Link to the Diagram.

However, I would think you would want to do that before performing the layout, so that the new node would be laid out correctly. You would need to explicitly add to the either the leftParts or the rightParts collections.

Read more about “unmodeled parts” at http://gojs.net/latest/intro/legends.html.

An unrelated comment: you’re calling parseInt on a number.

I made a copy of the samples/doubleTree.html file, and I added this template from your code:

    myDiagram.nodeTemplateMap.add("yellow",
      $(go.Node, "Auto",
        $(go.Shape, "RoundedRectangle", { fill: "yellow" }),
        $(go.TextBlock, "Scenario?",
          {
            margin: 5,
            width: 150,
            wrap: go.TextBlock.WrapFit,
            textAlign: "center"
          })
      ));

Note that I removed the position: and hard-coded the scenario text string.

Then in the doubleTreeLayout function I added this statement immediately after starting the transaction:

    diagram.model.addNodeData({
      category: "yellow", parent: "Root", dir: "right"
    });

The result:

Hi Walter,

Thanks for the reply, much appreciated.

So is “yellow” in the template definition the ID by which that template can be referenced, i.e. in the category field when addNodeData is called?

Unfortunately this isn’t quite what we’re trying to achieve - we need this node directly above the “Root” node so it looks like this

Only with a ‘join’ between the scenario and the root, something like:

Regards your comment about calling parseInt on a number - if I didn’t then

{
      position: new go.Point(leftPoint, -100)
}

freaks out…??

Sorry if this is all newbie stuff, but I’m a newbie with this library :-)

Oh, sorry, I completely misunderstood your intent. A screenshot does make it clearer.

Do you only want to add this one yellow node, as a “comment”? Then your approach to adding an unmodeled node and link make sense. Your original code is fine – you just need to add a Link, as I suggested above. But note that if you don’t add the information to the model, if you save the model that information will be missing.

Or did you want to add “comments” to other nodes as well? If so, you might want to consider this sample: http://gojs.net/latest/samples/comments.html.

Or did you mean to start a third tree, growing upwards? If so, I suggest that you implement exactly that, with a third value for the dir data property, and a third instance of TreeLayout working on a third partition of the nodes and links.

Actually, there are more scenarios that are plausible, but I can’t tell what you want.

All I’m after is a single extra panel like I’ve been able to render, and yes a Link is perfect… but how?

How do I reference my scenario in the Link.fromNode…? I know (presume) that the Link.toNode is “Root”, but what’s the name/id of my scenario node? From the API documentation it appears what I need is

diagram.model.addLinkData({ from: "????", to: "Root" });

But I don’t know how I determine what goes in the from? (The samples all seem to be more complex and presume that you’re building lots of nodes/links from arrays of each, I just need an example of how to link two things together - or even less, an example of how to ‘name’ a node so that it can be referenced by other things :-)

Modifying the Double Tree sample’s doubleTreeLayout function:

    var root = diagram.findNodeForKey("Root");

    var comment =
      $(go.Node, "Auto",
        {
          locationSpot: go.Spot.Center,
          location: new go.Point(root.actualBounds.centerX, -75)
        },
        $(go.Shape, "RoundedRectangle", { fill: "yellow" }),
        $(go.TextBlock, "This is a description of the scenario which I changed",
          {
            margin: 5,
            width: 150,
            wrap: go.TextBlock.WrapFit,
            textAlign: "center"
          })
      );
    diagram.add(comment);

    var link =
      $(go.Link, $(go.Shape));
    link.fromNode = diagram.findNodeForKey("Root");
    link.toNode = comment;
    diagram.add(link);

    diagram.commitTransaction("Double Tree Layout");

produces:

Perfect :-) So it’s the variable name which I needed to use.

Thank you so much for your assistance!