Programatically placing a node

Just trying some more experiments. Trying to place an initial node on the canvas “manually” (i.e. not dragged from the palette area over to the canvas).

 myDiagram.nodeTemplateMap.each(function(nodeType) {
 if(nodeType.key == 'testKey')
 {
   myDiagram.add(nodeType.value);
 }
});

This “works”, in that it shows the node on the canvas when it loads. However, when I drag a new node over from the palette, I can’t connect them together. Is it because the node placed via code isn’t instantiated or something? Thanks!

That’s part of it. The other problem is that now you have put nodes in the TemplateMap into a Diagram, which is a no-no.

Also there can be at most one template named “testKey”. Assuming such a template exists, try:

myDiagram.model.addNodeData({ category: "testKey"});

within a transaction, of course.

You’ll probably need to add some more properties on that new node data object to make it meaningful in your environment, depending on your template.

Yep, that did the trick! Yes, all of my keys are unique.

Walter, I don’t what they are paying you there, but I will say this: The attention that I’ve received as a prospect evaluating the product has been nothing short of phenomenal. That’s hard to find these days.

Cheers.

One interesting side effect I’ve discovered. When I drag a new node over to the canvas and try to connect it with the one that was placed via code, my port mouseover shows me that the ports are active, and I make the connection, but as soon as I do, the link itself gets drawn to the center of the side of the node rather than the port itself. Also, if I move that node around the other node, the link auto moves to the other sides. Cool feature, but … any idea what is causing it and how do I prevent it?

Do you have multiple ports? If so, the link that you create isn’t connecting to a specific port, so it connects with the default port, named “” (the empty string), or with the whole Node if no such object has portId == “”.

Read more about ports at GoJS Ports in Nodes-- Northwoods Software.

Note how multiple ports are only supported by GraphLinksModels with the linkToPortIdProperty and linkFromPortIdProperty set.

Yes, I have multiple ports on each node (4 on each side). and they all have unique names. I will read up on what you posted - thanks! I’m assuming that since it works fine with elements dragged in from the palette, that your response should be targeted at the node I am placing via code … ?

FWIW - All of my nodes are created via a makeTemplate() function, which calls a makePort() function to create the ports:

function makePort(name, spot, output, input, portSize) {
    var port = $(go.Shape, "RoundedRectangle",
    {
       fill: "lightgray",
       stroke: "darkgray",
       desiredSize: portSize,
       margin: new go.Margin(3, 3),
       alignment: spot,
       alignmentFocus: spot,
       portId: name,
       fromSpot: spot, toSpot: spot,
       fromLinkable: output, toLinkable: input,
       toMaxLinks: 1,
       cursor: "pointer"
    });

  return port;
}

Make sure that the Node data that you create (or copy – Model.copyNodeData) and add to the model has all of the data properties all correct for all of the ports.

Make sure that the Link data that you create and add to the model has all four node/port properties set correctly, along with whatever other properties you expect link data to have.

Hmm. I call the addNodeData well after all of my templates have been created. From the docs on addNodeData:

This will cause a Node or simple Part to be created (copying the template found in Diagram.nodeTemplateMap), added to the Diagram in some Layer (based on Part.layerName), and bound to the node data (resulting in Panel.data referring to that node data object). Does it not copy the port data over as well?

Also, I should add that in looking at my JSON model saved to the database, it uses the defaults of topid and frompid. I’ve tried setting them manually, as follows, but no love :(

go.linkFromPortIdProperty = 'frompid';
go.linkToPortIdProperty = 'topid';

Thanks for your help!

If you set Model | GoJS API and
Model | GoJS API

Tried:

myDiagram.copiesArrayObjects = true;
myDiagram.copiesArrays = true;

But no love.

The documentation is for the Model class.

[blush] … trying it now.

myDiagram.model.copiesArrayObjects = true;
myDiagram.model.copiesArrays = true;

Still no love. I get the same behavior.

You were asking about making sure that the Arrays of port descriptors in your node data would be copied, and not shared between nodes, right? If so, then you either need to set those two properties on Model, or you need to provide a custom copying function so that you can control exactly what is copied and what is shared.

But you need to do that on the GraphLinksModel that you are displaying. Are you setting those two properties on the Diagram.model and then discarding that Model by replacing it with a new one?

The whole thing is a wee bit confusing to me at the moment, apologies. My model is loaded as such:

myDiagram.model = go.Model.fromJson(document.getElementById("savedModel").value);

That DOM element is a hidden textarea that gets populated from the model JSON stored in the database. So, is my syntax above incorrect? (i.e. myDiagram.model.copiesArrayObjects, etc).

I don’t think I need a custom function, but again, I’m still learning the parlance of GoJS, so I could be wrong. What I am trying to do sounds simple enough (to me at least). I have defined a bunch of templates, and have a palette tied into it all, and I want to populate the canvas with one of them when the page loads. And of course, I want the nodes to work as they do when I don’t autopopulate the canvas with a node, and the user just drags the elements over themselves. Hope that makes sense.

I think I am overthinking this a bit. It has occurred to me that I could just provide a “default” JSON model which simply contains the node with no links on it … sigh.