Many applications will require the programmer to show different Diagrams in the same content area of the page. This is especially common in single-page webapps. Often, you do not need to remove the Diagram, and create another one, to do this. Since the Diagram is analogous to a view in a model-view architecture, you can instead replace the Diagram.model, and perhaps other settings, like the Diagram.nodeTemplateMap or Diagram.layout. Or you could build larger template maps that accommodate all Models you wish to present.
Below is an example of keeping a single Diagram, to be used as the view surface. It has a Model loaded, and a button will load a different Model which uses different templates, and sets a different Layout. This demonstrates re-use of the Diagram, which is often easier and more efficient than handling multiple Diagrams. This is a normal way to show at most one diagram at a time.
// A minimal Diagram
diagram.nodeTemplate =
new go.Node("Auto")
.add(
new go.Shape("RoundedRectangle")
.bind("fill", "color"),
new go.TextBlock({ margin: 3, font: '28px sans-serif' }) // some room around the text
.bind("text", "key")
);
// Node template that is only used by the second model
diagram.nodeTemplateMap.add("TypeTwo",
new go.Node("Horizontal")
.add(
new go.Shape("Circle", { width: 24, height: 24, strokeWidth: 0, portId: "" })
.bind("fill", "color"),
new go.TextBlock({ margin: 2, font: "Bold 15px sans-serif" })
.bind("text", "key")
)
);
// Another node template that is only used by the second model
diagram.nodeTemplateMap.add("AnotherType",
new go.Node("Auto")
.add(
new go.Shape("Rectangle", { strokeWidth: 1, fill: 'lightyellow' })
.bind("fill", "color"),
new go.TextBlock({ margin: 12, font: "12px sans-serif" })
.bind("text", "text")
)
);
let firstModel = true;
loadModel();
// Toggle the Diagram's Model
const button1 = document.getElementById('button1');
button1.addEventListener('click', () => {
loadModel();
});
function loadModel() {
if (firstModel) { // load the first model
diagram.layout = new go.Layout(); // Simple layout
diagram.model = new go.GraphLinksModel(
[
{ key: "Alpha", color: "lightblue" },
{ key: "Beta", color: "lightblue" },
{ key: "Gamma", color: "lightgreen" },
{ key: "Delta", color: "lightgreen" }
],
[
{ from: "Alpha", to: "Beta" },
{ from: "Gamma", to: "Delta" }
]);
} else { // load the second model
diagram.layout = new go.TreeLayout({ angle: 90 });
diagram.model = new go.GraphLinksModel(
[
{ key: "One", category: "TypeTwo", color: go.Brush.randomColor() },
{ key: "Two", category: "TypeTwo", color: go.Brush.randomColor() },
{ key: "Three", category: "TypeTwo", color: go.Brush.randomColor() },
{ key: "Four", category: "TypeTwo", color: go.Brush.randomColor() },
{ key: "Five", category: "TypeTwo", color: go.Brush.randomColor() },
{ key: "Six", category: "TypeTwo", color: go.Brush.randomColor() },
{ text: "Some comment", category: "AnotherType" }
],
[
{ from: "One", to: "Two" },
{ from: "One", to: "Three" },
{ from: "Three", to: "Four" },
{ from: "Three", to: "Five" },
{ from: "Four", to: "Six" }
]);
}
firstModel = !firstModel;
}
Note that changing the Model destroys all state not kept in the Model, such as the currently selected Parts, and if there are no data bindings for them, the positions of all Nodes as well, and so on. These can be saved in the Model before switching, when they are relevant.
Sometimes users want to work on two or more Diagrams at once and keep all Diagram state. If this is the case, you may wish to put two Diagrams on the page (as all samples with a Palette do), or you may wish to put Diagrams into multiple "tabs" or some other mechanism, like the Planogram sample does with its four Palettes.
Alternatively, you may wish to display the two Diagrams in the same Div, one at a time, by swapping them out.
You can swap the Div by setting Diagram.div to null
on the first Diagram,
and setting the Div on the second.
// A very minimal Diagram
diagram.nodeTemplate =
new go.Node("Auto")
.add(
new go.Shape("Circle")
.bind("fill", "color"),
new go.TextBlock({ margin: 3 }) // some room around the text
.bind("text", "key")
);
diagram.model = new go.GraphLinksModel([
{ key: "Alpha", color: "lightblue" },
{ key: "Beta", color: "orange" }
], [
{ from: "Alpha", to: "Beta" },
]);
const diagram2 = new go.Diagram();
diagram2.nodeTemplate =
new go.Node("Auto")
.add(
new go.Shape("Rectangle", { fill: 'lime' }),
new go.TextBlock({ margin: 5, font: '22px sans-serif' })
.bind("text", "key")
);
diagram2.model = new go.GraphLinksModel([
{ key: "BigNode1" },
{ key: "BigNode2" },
{ key: "BigNode3" },
], [ ]);
let currentDiagram = diagram;
// Toggle the Diagram within this Div with this button
const button2 = document.getElementById('button2');
button2.addEventListener('click', () => {
// Set one Diagram.div to null, and the other Diagram.div to this div
if (currentDiagram === diagram) {
const div = diagram.div;
diagram.div = null;
diagram2.div = div;
currentDiagram = diagram2;
} else {
const div = diagram2.div;
diagram2.div = null;
diagram.div = div;
currentDiagram = diagram;
}
});
If you select a Node and move it, and toggle Diagrams back and forth, you will see that the selection and Node positioning persists. Both Diagrams remain in memory, only the Div is swapped to use one or the other.
You may wish to remove a Diagram and ensure it leaves no memory footprint. To do this, if you have not created any other references to your Diagram or GraphObjects or Tools or Layouts within, you can write:
myDiagram.div = null;
myDiagram = null; // Assumes this is the only reference to your Diagram
If you have used Pictures, you should also clear the Picture cache, which GoJS creates to store a map of source URLs to Image elements:
// Clear any Image references that GoJS is holding onto
go.Picture.clearCache();