I have simple python flask goJS graph application which looks like this:
Sources for node and link texts are loaded from backend side of app and I set them in model.modelData
part like this:
var graphDataString = JSON.parse('{{ diagramData | tojson | safe}}'); myDiagram.model = go.Model.fromJson(graphDataString); myDiagram.model.set(myDiagram.model.modelData, "linkchoices", JSON.parse('{{ link_choices | tojson | safe}}')); myDiagram.model.set(myDiagram.model.modelData, "nodechoices", JSON.parse('{{ node_choices | tojson | safe}}')); console.log("whole model"); console.log(myDiagram.model.modelData);
it all loads fine into modelData and I can write it to console without problems:
My problem is that it doesn't show on my nodes and link dropdowns, and I don't know why.
This is my node template:
myDiagram.nodeTemplate = $(go.Node, "Auto", new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify), // define the node's outer shape, which will surround the TextBlock $(go.Shape, "RoundedRectangle", { parameter1: 20, // the corner has a large radius fill: $(go.Brush, "Linear", { 0: "rgb(254, 201, 0)", 1: "rgb(254, 162, 0)" }), stroke: null, portId: "", // this Shape is the Node's port, not the whole Node fromLinkable: true, fromLinkableDuplicates: true, toLinkable: true, toLinkableDuplicates: true, cursor: "pointer" }), $(go.TextBlock, { font: "bold 11pt helvetica, bold arial, sans-serif", editable: true, // editing the text automatically updates the model data //textEditor: window.TextEditorRadioButtons, // defined in textEditorRadioButtons.js // this specific TextBlock has its own choices: textEditor: window.TextEditorSelectBox, // defined in extensions/textEditorSelectBox.js textEdited: function(tb, oldstr, newstr) { var currentNodeChoices = tb.diagram.model.modelData.nodechoices; console.log("currentNodeChoices"); console.log(currentNodeChoices); console.log("newstr"); console.log(newstr); console.log("oldstr"); console.log(oldstr); var idx = currentNodeChoices.indexOf(newstr); if (idx >= 0 && oldstr !== newstr) { console.log("removing choice " + idx + ": " + newstr); var newNodeChoices = Array.prototype.slice.call(currentNodeChoices); newNodeChoices.splice(idx, 1); tb.diagram.model.set(tb.diagram.model.modelData, "nodechoices", newNodeChoices); } } }, new go.Binding("text").makeTwoWay(), new go.Binding("nodechoices").ofModel()) );
This is my link template:
myDiagram.linkTemplate = $(go.Link, // the whole link panel { curve: go.Link.Bezier, adjusting: go.Link.Stretch, reshapable: true, relinkableFrom: true, relinkableTo: true, toShortLength: 3 }, new go.Binding("points").makeTwoWay(), new go.Binding("curviness"), $(go.Shape, // the link shape { strokeWidth: 1.5 }), $(go.Shape, // the arrowhead { toArrow: "standard", stroke: null }), $(go.Panel, "Auto", $(go.Shape, // the label background, which becomes transparent around the edges { fill: $(go.Brush, "Radial", { 0: "rgb(240, 240, 240)", 0.3: "rgb(240, 240, 240)", 1: "rgba(240, 240, 240, 0)" }), stroke: null }), $(go.TextBlock, { background: "white", editable: true, textEditor: window.TextEditorSelectBox, // defined in extensions/textEditorSelectBox.js textEdited: function(tb, oldstr, newstr) { var currentLinkChoices = tb.diagram.model.modelData.linkchoices; console.log("currentLinkChoices"); console.log(currentLinkChoices); console.log("newstr"); console.log(newstr); console.log("oldstr"); console.log(oldstr); var idx = currentLinkChoices.indexOf(newstr); if (idx >= 0 && oldstr !== newstr) { console.log("removing choice " + idx + ": " + newstr); var newLinkChoices = Array.prototype.slice.call(currentLinkChoices); newLinkChoices.splice(idx, 1); tb.diagram.model.set(tb.diagram.model.modelData, "linkchoices", newLinkChoices); } } }, new go.Binding("text").makeTwoWay(), new go.Binding("linkchoices").ofModel()) ) );
I want to accomplish this behaviour: User can add new nodes and links but user can only choose available options from dropdown for links and nodes. Adding new nodes and links works fine and I don't have any problems with it. I want to make so that when user uses one option for node, that option is not available again until he deletes that node or change it for some other option.
For example he uses "node_choice_1" he can not use it anymore on any other node until he changes that option on that node or deletes node. Same goes for links. So I added this code to my diagram definition:
myDiagram = $(go.Diagram, "myDiagramDiv", // must name or refer to the DIV HTML element { // start everything in the middle of the viewport initialContentAlignment: go.Spot.Center, // have mouse wheel events zoom in and out instead of scroll up and down "toolManager.mouseWheelBehavior": go.ToolManager.WheelZoom, // support double-click in background creating a new node "clickCreatingTool.archetypeNodeData": { text: "new node" }, // enable undo & redo "textEditingTool.defaultTextEditor": window.TextEditorSelectBox, "undoManager.isEnabled": true, "layout": new go.ForceDirectedLayout(), "ModelChanged": function(e) { console.log("Diagram model changed!"); if (e.change === go.ChangedEvent.Remove && e.modelChange === "linkDataArray") { console.log("eee"); console.log(e); var linkdata = e.oldValue; console.log("linkdata"); console.log(linkdata); var oldstr = linkdata.text; console.log("oldstr"); console.log(oldstr); if (!oldstr) return; var currentLinkChoices = e.model.modelData.linkchoices; console.log("currentLinkChoices"); console.log(currentLinkChoices); var idx = currentLinkChoices.indexOf(oldstr); if (idx < 0) { console.log("adding choice: " + oldstr); var newLinkChoices = Array.prototype.slice.call(currentLinkChoices); newLinkChoices.push(oldstr); e.model.set(e.model.modelData, "linkchoices", newLinkChoices); } } else if(e.change === go.ChangedEvent.Remove && e.modelChange === "nodeDataArray"){ console.log("eee"); console.log(e); var nodedata = e.oldValue; console.log("nodedata"); console.log(nodedata); var oldstr = nodedata.text; console.log("oldstr"); console.log(oldstr); if (!oldstr) return; var currentNodeChoices = e.model.modelData.nodechoices; console.log("currentNodeChoices"); console.log(currentNodeChoices); var idx = currentNodeChoices.indexOf(oldstr); if (idx < 0) { console.log("adding choice: " + oldstr); var newNodeChoices = Array.prototype.slice.call(currentNodeChoices); newNodeChoices.push(oldstr); e.model.set(e.model.modelData, "nodechoices", newNodeChoices); } } } });
Also, when there are no more available node options for nodes user can not add any more nodes. Same goes for links.
I am getting really desperate because I am trying to make this simple thing to work and I am stuck in place for days. I tried to read documentation, but haven't found anything useful, there are so many documented cases, but no examples for what I need. Any help will be greatly appreciated.