The following code has two models in it. One is what you’d send to the client to run without a TableLayout, and one is what you would layout on the server. The latter is what it loads by default, which means it is requiring the TableLayout.
Modify the templates to remove the Group.layout and the TwoWay Bindings and then hit the “Load” button to see what result you would get on the client.
<!DOCTYPE html>
<html>
<head>
<title>Minimal GoJS Sample</title>
<!-- Copyright 1998-2023 by Northwoods Software Corporation. -->
</head>
<body>
<div id="myDiagramDiv" style="border: solid 1px black; width:100%; height:600px"></div>
<!-- this model includes "loc" and "size" and "expanded" property values,
and thus does not require Group.layout being a TableLayout nor any TwoWay Bindings -->
<textarea id="mySavedModel" style="width:100%;height:250px">
{ "class": "GraphLinksModel",
"nodeDataArray": [
{"key":1,"isGroup":true,"loc":"4 37.81052598953246"},
{"key":2,"isGroup":true,"group":1,"row":0,"col":0,"loc":"12 79.62105197906494","size":"220 81.61052598953248"},
{"key":3,"isGroup":true,"group":1,"row":0,"col":1,"loc":"240 79.62105197906494","size":"327 81.61052598953248"},
{"key":4,"isGroup":true,"group":1,"row":0,"col":2,"loc":"575 79.62105197906494","size":"100 50","expanded":false},
{"key":5,"isGroup":true,"group":1,"row":0,"col":3,"loc":"683 79.62105197906494","size":"115 81.61052598953248"},
{"key":6,"isGroup":true,"group":1,"row":0,"col":4,"loc":"806 79.62105197906493","size":"346 131.92105197906494"},
{"key":7,"isGroup":true,"group":6,"row":0,"col":0,"loc":"814 121.43157796859742","size":"221 81.61052598953248"},
{"key":8,"isGroup":true,"group":6,"row":0,"col":1,"loc":"1043 121.43157796859741","size":"100 50","expanded":false},
{"key":9,"isGroup":true,"group":1,"row":1,"col":0,"loc":"12 219.54210395812987","size":"220 81.61052598953248"},
{"key":10,"isGroup":true,"group":1,"row":1,"col":1,"colSpan":3,"loc":"240 219.54210395812987","size":"558 50","expanded":false},
{"group":2,"row":0,"col":0,"key":-11,"loc":"20 87.62105197906494"},
{"group":2,"row":0,"col":1,"key":-12,"loc":"125 87.62105197906494"},
{"group":3,"row":0,"col":0,"key":-13,"loc":"248 87.62105197906494"},
{"group":3,"row":0,"col":1,"key":-14,"loc":"354 87.62105197906494"},
{"group":3,"row":0,"col":2,"key":-15,"loc":"460 87.62105197906494"},
{"group":4,"row":0,"col":0,"key":-16,"loc":"583 87.62105197906494"},
{"group":4,"row":0,"col":1,"key":-17,"loc":"689 87.62105197906494"},
{"group":4,"row":0,"col":2,"key":-18,"loc":"795 87.62105197906494"},
{"group":4,"row":0,"col":3,"key":-19,"loc":"901 87.62105197906494"},
{"group":5,"row":0,"col":0,"key":-20,"loc":"691 87.62105197906494"},
{"group":7,"row":0,"col":0,"key":-21,"loc":"822 129.43157796859742"},
{"group":7,"row":0,"col":1,"key":-22,"loc":"928 129.43157796859742"},
{"group":8,"row":0,"col":0,"key":-23,"loc":"1051 129.43157796859742"},
{"group":8,"row":0,"col":1,"key":-24,"loc":"1157 129.43157796859742"},
{"group":8,"row":0,"col":2,"key":-25,"loc":"1263 129.43157796859742"},
{"group":9,"row":0,"col":0,"key":-26,"loc":"20 227.54210395812987"}
],
"linkDataArray": []}
</textarea>
<div>
<button id="myLoadButton">Load</button>
<button id="mySaveButton">Save</button>
</div>
<script src="go.js"></script>
<script src="../extensions/TableLayout.js"></script>
<script id="code">
const $ = go.GraphObject.make;
const myDiagram =
$(go.Diagram, "myDiagramDiv",
{
"undoManager.isEnabled": true,
"ModelChanged": e => { // just for demonstration purposes,
if (e.isTransactionFinished) { // show the model data in the page's TextArea
document.getElementById("mySavedModel").textContent = e.model.toJson();
}
}
});
myDiagram.nodeTemplate =
$(go.Node, "Auto",
{
alignment: go.Spot.Left,
margin: 4
},
new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
new go.Binding("row", "row"), // these all affect TableLayout of containing Group
new go.Binding('column', 'col'),
new go.Binding('columnSpan', 'colSpan'),
$(go.Shape,
{ fill: "white" },
new go.Binding("fill", "color")),
$(go.TextBlock,
{ margin: 8 },
new go.Binding("text", "key", k => `Node key: ${k}`))
);
myDiagram.groupTemplate =
$(go.Group, "Vertical",
{
alignment: go.Spot.TopLeft, // affects TableLayout of containing group
stretch: go.GraphObject.Horizontal,
margin: 4, // affects TableLayout of containing group
layout: $(TableLayout), // affects arrangement of member nodes
minSize: new go.Size(100, 50), // affects this panel (i.e. whole group)
defaultStretch: go.GraphObject.Horizontal // affects elements of this panel
},
new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
new go.Binding("desiredSize", "size", go.Size.parse).makeTwoWay(go.Size.stringify),
new go.Binding("row", "row"), // these all affect TableLayout of containing Group
new go.Binding("column", "col"),
new go.Binding("columnSpan", "colSpan"),
new go.Binding("isSubGraphExpanded", "expanded").makeTwoWay(),
// the header
$(go.Panel, "Table",
{ padding: new go.Margin(8, 4), background: "green" },
new go.Binding("background", "color"),
$(go.Panel, "Horizontal",
$("SubGraphExpanderButton"),
$(go.TextBlock,
{ font: "bold 12pt sans-serif", margin: new go.Margin(0, 4) },
new go.Binding("text", "", data => `Table: ${data.key}`)
)
)
),
// the body holding the member nodes
$(go.Panel, "Auto",
$(go.Shape, { fill: null }),
$(go.Placeholder, { padding: 8, alignment: go.Spot.Left })
)
);
// this requires Group.layout being a TableLayout:
myDiagram.model = new go.GraphLinksModel(
[
{ key: 1, isGroup: true },
{ key: 2, isGroup: true, group: 1, row: 0, col: 0 },
{ key: 3, isGroup: true, group: 1, row: 0, col: 1 },
{ key: 4, isGroup: true, group: 1, row: 0, col: 2 },
{ key: 5, isGroup: true, group: 1, row: 0, col: 3 },
{ key: 6, isGroup: true, group: 1, row: 0, col: 4 },
{ key: 7, isGroup: true, group: 6, row: 0, col: 0 },
{ key: 8, isGroup: true, group: 6, row: 0, col: 1 },
{ key: 9, isGroup: true, group: 1, row: 1, col: 0 },
{ key: 10, isGroup: true, group: 1, row: 1, col: 1, colSpan: 3 },
{ group: 2, row: 0, col: 0 },
{ group: 2, row: 0, col: 1 },
{ group: 3, row: 0, col: 0 },
{ group: 3, row: 0, col: 1 },
{ group: 3, row: 0, col: 2 },
{ group: 4, row: 0, col: 0 },
{ group: 4, row: 0, col: 1 },
{ group: 4, row: 0, col: 2 },
{ group: 4, row: 0, col: 3 },
{ group: 5, row: 0, col: 0 },
{ group: 7, row: 0, col: 0 },
{ group: 7, row: 0, col: 1 },
{ group: 8, row: 0, col: 0 },
{ group: 8, row: 0, col: 1 },
{ group: 8, row: 0, col: 2 },
{ group: 9, row: 0, col: 0 },
]);
// save a model to and load a model from Json text, displayed below the Diagram
function save() {
var str = myDiagram.model.toJson();
document.getElementById("mySavedModel").value = str;
}
document.getElementById("mySaveButton").addEventListener("click", save);
function load() {
var str = document.getElementById("mySavedModel").value;
myDiagram.model = go.Model.fromJson(str);
}
document.getElementById("myLoadButton").addEventListener("click", load);
</script>
</body>
</html>