226 lines
8.8 KiB
HTML
226 lines
8.8 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Minimal GoJS Sample in Vue.js</title>
|
|
<meta name="description" content="Interactive diagram implemented by GoJS using Vue.js, including a diagram component and model binding." />
|
|
<!-- Copyright 1998-2017 by Northwoods Software Corporation. -->
|
|
<meta charset="UTF-8">
|
|
<script src="../release/go.js"></script>
|
|
<script src="../assets/js/goSamples.js"></script> <!-- this is only for the GoJS Samples framework -->
|
|
<script src="https://unpkg.com/vue"></script>
|
|
<script id="code">
|
|
function init() {
|
|
if (window.goSamples) goSamples(); // init for these samples -- you don't need to call this
|
|
|
|
var $ = go.GraphObject.make;
|
|
|
|
Vue.component("diagram", {
|
|
template: "<div></div>", // just a plain DIV
|
|
props: ["modelData"], // accept model data as a parameter
|
|
data: function() { return { diagram: null } }, // provide access to the GoJS Diagram
|
|
mounted: function() {
|
|
var self = this;
|
|
var myDiagram =
|
|
$(go.Diagram, this.$el,
|
|
{
|
|
initialContentAlignment: go.Spot.Center,
|
|
layout: $(go.TreeLayout, { angle: 90, arrangement: go.TreeLayout.ArrangementHorizontal }),
|
|
"undoManager.isEnabled": true,
|
|
// Model ChangedEvents get passed up to component users
|
|
"ModelChanged": function(e) { self.$emit("model-changed", e); },
|
|
"ChangedSelection": function(e) { self.$emit("changed-selection", e); }
|
|
});
|
|
|
|
myDiagram.nodeTemplate =
|
|
$(go.Node, "Auto",
|
|
$(go.Shape,
|
|
{
|
|
fill: "white", strokeWidth: 0,
|
|
portId: "", fromLinkable: true, toLinkable: true, cursor: "pointer"
|
|
},
|
|
new go.Binding("fill", "color")),
|
|
$(go.TextBlock,
|
|
{ margin: 8, editable: true },
|
|
new go.Binding("text").makeTwoWay())
|
|
);
|
|
|
|
myDiagram.linkTemplate =
|
|
$(go.Link,
|
|
{ relinkableFrom: true, relinkableTo: true },
|
|
$(go.Shape),
|
|
$(go.Shape, { toArrow: "OpenTriangle" })
|
|
);
|
|
|
|
this.diagram = myDiagram;
|
|
|
|
this.updateModel(this.modelData);
|
|
},
|
|
watch: {
|
|
modelData: function(val) { this.updateModel(val); }
|
|
},
|
|
methods: {
|
|
model: function() { return this.diagram.model; },
|
|
updateModel: function(val) {
|
|
// No GoJS transaction permitted when replacing Diagram.model.
|
|
if (val instanceof go.Model) {
|
|
this.diagram.model = val;
|
|
} else {
|
|
var m = new go.GraphLinksModel()
|
|
if (val) {
|
|
for (var p in val) {
|
|
m[p] = val[p];
|
|
}
|
|
}
|
|
this.diagram.model = m;
|
|
}
|
|
},
|
|
updateDiagramFromData: function() {
|
|
this.diagram.startTransaction();
|
|
// This is very general but very inefficient.
|
|
// It would be better to modify the diagramData data by calling
|
|
// Model.setDataProperty or Model.addNodeData, et al.
|
|
this.diagram.updateAllRelationshipsFromData();
|
|
this.diagram.updateAllTargetBindings();
|
|
this.diagram.commitTransaction("updated");
|
|
}
|
|
}
|
|
})
|
|
|
|
|
|
myApp = new Vue({
|
|
el: "#sample",
|
|
data: {
|
|
diagramData: { // passed to <diagram> as its modelData
|
|
nodeDataArray: [
|
|
{ key: 1, text: "Alpha", color: "lightblue" },
|
|
{ key: 2, text: "Beta", color: "orange" },
|
|
{ key: 3, text: "Gamma", color: "lightgreen" },
|
|
{ key: 4, text: "Delta", color: "pink" }
|
|
],
|
|
linkDataArray: [
|
|
{ from: 1, to: 2 },
|
|
{ from: 1, to: 3 },
|
|
{ from: 3, to: 4 }
|
|
]
|
|
},
|
|
currentNode: null,
|
|
savedModelText: "",
|
|
counter: 1, // used by addNode
|
|
counter2: 4 // used by modifyStuff
|
|
},
|
|
computed: {
|
|
currentNodeText: {
|
|
get: function() {
|
|
var node = this.currentNode;
|
|
if (node instanceof go.Node) {
|
|
return node.data.text;
|
|
} else {
|
|
return "";
|
|
}
|
|
},
|
|
set: function(val) {
|
|
var node = this.currentNode;
|
|
if (node instanceof go.Node) {
|
|
var model = this.model();
|
|
model.startTransaction();
|
|
model.setDataProperty(node.data, "text", val);
|
|
model.commitTransaction("edited text");
|
|
}
|
|
}
|
|
}
|
|
},
|
|
methods: {
|
|
// get access to the GoJS Model of the GoJS Diagram
|
|
model: function() { return this.$refs.diag.model(); },
|
|
|
|
// tell the GoJS Diagram to update based on the arbitrarily modified model data
|
|
updateDiagramFromData: function() { this.$refs.diag.updateDiagramFromData(); },
|
|
|
|
// this event listener is declared on the <diagram>
|
|
modelChanged: function(e) {
|
|
if (e.isTransactionFinished) { // show the model data in the page's TextArea
|
|
this.savedModelText = e.model.toJson();
|
|
}
|
|
},
|
|
|
|
changedSelection: function(e) {
|
|
var node = e.diagram.selection.first();
|
|
if (node instanceof go.Node) {
|
|
this.currentNode = node;
|
|
this.currentNodeText = node.data.text;
|
|
} else {
|
|
this.currentNode = null;
|
|
this.currentNodeText = "";
|
|
}
|
|
},
|
|
|
|
// Here we modify the GoJS Diagram's Model using its methods,
|
|
// which can be much more efficient than modifying some memory and asking
|
|
// the GoJS Diagram to find differences and update accordingly.
|
|
// Undo and Redo will work as expected.
|
|
addNode: function() {
|
|
var model = this.model();
|
|
model.startTransaction();
|
|
model.setDataProperty(model.findNodeDataForKey(4), "color", "purple");
|
|
var data = { text: "NEW " + this.counter++, color: "yellow" };
|
|
model.addNodeData(data);
|
|
model.addLinkData({ from: 3, to: model.getKeyForNodeData(data) });
|
|
model.commitTransaction("added Node and Link");
|
|
// also manipulate the Diagram by changing its Diagram.selection collection
|
|
var diagram = this.$refs.diag.diagram;
|
|
diagram.select(diagram.findNodeForData(data));
|
|
},
|
|
|
|
// Here we modify VUE's view model directly, and
|
|
// then ask the GoJS Diagram to update everything from the data.
|
|
// This is less efficient than calling the appropriate GoJS Model methods.
|
|
// NOTE: Undo will not be able to restore all of the state properly!!
|
|
modifyStuff: function() {
|
|
var data = this.diagramData;
|
|
data.nodeDataArray[0].color = "red";
|
|
// Note here that because we do not have the GoJS Model,
|
|
// we cannot find out what values would be unique keys, for reference by the link data.
|
|
data.nodeDataArray.push({ key: ++this.counter2, text: this.counter2.toString(), color: "orange" });
|
|
data.linkDataArray.push({ from: 2, to: this.counter2 });
|
|
this.updateDiagramFromData();
|
|
}
|
|
}
|
|
})
|
|
}
|
|
</script>
|
|
</head>
|
|
<body onload="init()">
|
|
<div id="sample">
|
|
<diagram ref="diag"
|
|
v-bind:model-data="diagramData"
|
|
v-on:model-changed="modelChanged"
|
|
v-on:changed-selection="changedSelection"
|
|
style="border: solid 1px black; width:100%; height:400px"></diagram>
|
|
<button v-on:click="addNode">Add Child to Gamma</button>
|
|
<button v-on:click="modifyStuff">Modify view model data without undo</button>
|
|
<br/>Current Node:
|
|
<input v-model.lazy="currentNodeText" v-bind:disabled="currentNode === null"/>
|
|
<br/>The saved GoJS Model:
|
|
<textarea style="width:100%;height:250px">{{ savedModelText }}</textarea>
|
|
<p class="box bg-info">
|
|
This is a <a href="https://vuejs.org">Vue.js</a> sample.
|
|
</p>
|
|
<p>
|
|
The GoJS Diagram is held in a "diagram" component, and only exposes a small fraction of the functionality of <a>Diagram</a>.
|
|
That includes the "modelData" property, to initialize the Diagram to show a model, and
|
|
the "diagram" property, to get access to the <a>Diagram</a>.
|
|
</p>
|
|
<p>
|
|
That component also raises two events: "model-changed" corresponding to <a>Model.addChangedListener</a>, and
|
|
"changed-selection" for the "ChangedSelection" <a>DiagramEvent</a>.
|
|
</p>
|
|
<p>
|
|
That component also supports two different ways of modifying the diagram: access to the <a>Model</a> via the "model" method
|
|
so that code can call Model methods such as <a>Model.setDataProperty</a>, and an "updateDiagramFromData" method.
|
|
The latter permits data changes without calling Model methods to notify Diagrams showing the model,
|
|
but at the cost of not being able to support undo and redo.
|
|
</p>
|
|
</div>
|
|
</body>
|
|
</html> |