feat: 后端全量更新 - 含所有本次需求
- Contract.php: 返回合约账户余额(balance_contract) - My.php: 地址管理增加BTC/ETH - AppContract.php: 一键平仓(closeall) - AppProxy.php: 代理专属注册链接 + 分级权限(L1/L2) - site.php: 手续费减半(0.018→0.009) - agent_permission_setup.sql: 代理权限SQL - crypto_news_crawler.py: 新闻自动采集脚本
This commit is contained in:
Executable
+506
@@ -0,0 +1,506 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>GoJS Using Models -- Northwoods Software</title>
|
||||
<!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
|
||||
<script src="../release/go.js"></script>
|
||||
<script src="goIntro.js"></script>
|
||||
</head>
|
||||
<body onload="goIntro()">
|
||||
<div id="container" class="container-fluid">
|
||||
<div id="content">
|
||||
|
||||
<h1>Using Models and Templates</h1>
|
||||
<p>
|
||||
You can build a diagram of nodes and links programmatically.
|
||||
But <b>GoJS</b> offers a way to build diagrams in a more declarative manner.
|
||||
You only provide the node and link data (i.e. the model) necessary for the diagram
|
||||
and instances of parts (i.e. the templates) that are automatically copied into the diagram.
|
||||
Those templates may be parameterized by properties of the node and link data.
|
||||
</p>
|
||||
|
||||
<h2 id="BuildingDiagramsWithCode">Building diagrams with code</h2>
|
||||
<p>
|
||||
Let us try to build two nodes and connect them with a link.
|
||||
Here is one way of doing that:
|
||||
</p>
|
||||
<pre class="lang-js" id="twoNodesOneLinkCode">
|
||||
var node1 =
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape,
|
||||
{ figure: "RoundedRectangle",
|
||||
fill: "lightblue" }),
|
||||
$(go.TextBlock,
|
||||
{ text: "Alpha",
|
||||
margin: 5 })
|
||||
)
|
||||
diagram.add(node1);
|
||||
|
||||
var node2 =
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape,
|
||||
{ figure: "RoundedRectangle",
|
||||
fill: "pink" }),
|
||||
$(go.TextBlock,
|
||||
{ text: "Beta",
|
||||
margin: 5 })
|
||||
);
|
||||
diagram.add(node2);
|
||||
|
||||
diagram.add(
|
||||
$(go.Link,
|
||||
{ fromNode: node1, toNode: node2 },
|
||||
$(go.Shape)
|
||||
));
|
||||
</pre>
|
||||
<script>goCode("twoNodesOneLinkCode", 250, 150)</script>
|
||||
<p>
|
||||
This produces a nice, simple diagram.
|
||||
If you drag one of the nodes, you will see that the link remains connected to it.
|
||||
</p>
|
||||
<p>
|
||||
Although this way of building a diagram will work, it will not scale up well when creating large diagrams.
|
||||
Normally you will want a varying number of nodes each of which is very similar to the others.
|
||||
It would be better to share the construction of the node but parameterize a few things where the values should vary.
|
||||
</p>
|
||||
<p>
|
||||
One possibility would be put the code to build a Node into a function that returned a fully constructed Node,
|
||||
including all of the Panels and other GraphObjects in its visual tree.
|
||||
You would probably want to parameterize the function in order to provide the desired strings and colors and figures and image URLs.
|
||||
However such an approach is very ad-hoc: it would be difficult for the system to know how to automatically call such functions
|
||||
in order to create new nodes or new links on demand.
|
||||
Furthermore as your application data changes dynamically, how would you use such functions to update properties
|
||||
of existing objects within existing nodes and links, without inefficiently re-creating everything?
|
||||
And if you wanted anything/everything to update automatically as your application data changes,
|
||||
how would the system know what to do?
|
||||
</p>
|
||||
<p>
|
||||
This diagram-building code is also more cumbersome than it needs to be
|
||||
to manage references to nodes so that you can link them up.
|
||||
This is similar to the earlier problem when building a node's visual tree in code
|
||||
of having to use temporary named variables and referring to them when needed.
|
||||
</p>
|
||||
<p>
|
||||
What we are looking for is the separation of the appearance, definition, and construction
|
||||
of all of the nodes from the application data needed to describe the unique aspects of each particular node.
|
||||
</p>
|
||||
|
||||
<h2 id="UsingModelAndTemplates">Using a Model and Templates</h2>
|
||||
<p>
|
||||
One way of achieving the separation of node appearance from node data is to use a data model and node templates.
|
||||
A model is basically just a collection of data that holds the essential information for each node and each link.
|
||||
A template is basically just a <a>Part</a> that can be copied; you would have different templates for <a>Node</a>s and for <a>Link</a>s.
|
||||
</p>
|
||||
<p>
|
||||
In fact, a <a>Diagram</a> already has very simple default templates for Nodes and Links.
|
||||
If you want to customize the appearance of the nodes in your diagram,
|
||||
you can replace the default node template by setting <a>Diagram.nodeTemplate</a>.
|
||||
</p>
|
||||
<p>
|
||||
To automatically make use of templates, provide the diagram a model holding the data for each node and the data for each link.
|
||||
A <a>GraphLinksModel</a> holds the collections (actually arrays) of node data and link data as the values of
|
||||
<a>GraphLinksModel.nodeDataArray</a> and <a>GraphLinksModel.linkDataArray</a>.
|
||||
You then set the <a>Diagram.model</a> property so that the diagram can create <a>Node</a>s for all of the node data
|
||||
and <a>Link</a>s for all of the link data.
|
||||
</p>
|
||||
<p>
|
||||
Models interpret and maintain references between the data.
|
||||
Each node data is expected to have a unique key value so that references to node data can be resolved reliably.
|
||||
Models also manage dynamically adding and removing data.
|
||||
</p>
|
||||
<p>
|
||||
The node data and the link data in models can be any JavaScript object.
|
||||
You get to decide what properties those objects have -- add as many as you need for your app.
|
||||
Since this is JavaScript, you can even add properties dynamically.
|
||||
There are several properties that <b>GoJS</b> models assume exist on the data,
|
||||
such as "key" (on node data) and "category" and "from" and "to" (the latter two on link data).
|
||||
However you can tell the model to use different property names by setting the model
|
||||
properties whose names end in "...Property".
|
||||
</p>
|
||||
<p>
|
||||
A node data object normally has its node's unique key value in the "key" property.
|
||||
Currently node data keys must be strings or numbers.
|
||||
You can get the key for a Node either via the <a>Node.key</a> property or via <code>someNode.data.key</code>.
|
||||
</p>
|
||||
<p>
|
||||
Let us create a diagram providing the minimal amount of necessary information.
|
||||
The particular node data has been put into an array of JavaScript objects.
|
||||
We declare the link relationships in a separate array of link data objects.
|
||||
Each link data holds references to the node data by using their keys.
|
||||
Normally the references are the values of the "from" and "to" properties.
|
||||
</p>
|
||||
<pre class="lang-js" id="simpleModelNoTemplates">
|
||||
var nodeDataArray = [
|
||||
{ key: "Alpha"},
|
||||
{ key: "Beta" }
|
||||
];
|
||||
var linkDataArray = [
|
||||
{ from: "Alpha", to: "Beta" }
|
||||
];
|
||||
diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
|
||||
</pre>
|
||||
<script>goCode("simpleModelNoTemplates", 250, 150)</script>
|
||||
<p>
|
||||
This results in two nodes and a link, but the nodes do not appear the way we want.
|
||||
So we define the node template to be a generalization of the particular node constructions that we did above.
|
||||
</p>
|
||||
<pre class="lang-js" id="simpleModelNoBind">
|
||||
diagram.nodeTemplate = // provide custom Node appearance
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape,
|
||||
{ figure: "RoundedRectangle",
|
||||
fill: "white" }),
|
||||
$(go.TextBlock,
|
||||
{ text: "hello!",
|
||||
margin: 5 })
|
||||
);
|
||||
|
||||
var nodeDataArray = [
|
||||
{ key: "Alpha" },
|
||||
{ key: "Beta" }
|
||||
];
|
||||
var linkDataArray = [
|
||||
{ from: "Alpha", to: "Beta" }
|
||||
];
|
||||
diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
|
||||
</pre>
|
||||
<script>goCode("simpleModelNoBind", 250, 150)</script>
|
||||
<p>
|
||||
Now the graph looks better, but the nodes have not been parameterized -- they are all identical!
|
||||
We can achieve that parameterization by using data binding.
|
||||
</p>
|
||||
|
||||
<h2 id="ParameterizingNodesUsingDataBindings">Parameterizing Nodes using data binding</h2>
|
||||
<p>
|
||||
A data binding is a declarative statement that the value of the property of one object
|
||||
should be used to set the value of a property of another object.
|
||||
</p>
|
||||
<p>
|
||||
In this case, we want to make sure that the <a>TextBlock.text</a> property gets the
|
||||
"key" value of the corresponding node data.
|
||||
And we want to make sure that the <a>Shape.fill</a> property gets set to the color/brush given
|
||||
by the "color" property value of the corresponding node data.
|
||||
</p>
|
||||
<p>
|
||||
We can declare such data-bindings by creating <a>Binding</a> objects and associating them with the target <a>GraphObject</a>.
|
||||
Programmatically you do this by calling <a>GraphObject.bind</a>.
|
||||
But when using <b>go.GraphObject.make</b>, this happens automatically when you pass in a <a>Binding</a>.
|
||||
</p>
|
||||
<pre class="lang-js" id="simpleModelWithBind">
|
||||
diagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape,
|
||||
{ figure: "RoundedRectangle",
|
||||
fill: "white" }, // default Shape.fill value
|
||||
new go.Binding("fill", "color")), // binding to get fill from nodedata.color
|
||||
$(go.TextBlock,
|
||||
{ margin: 5 },
|
||||
new go.Binding("text", "key")) // binding to get TextBlock.text from nodedata.key
|
||||
);
|
||||
|
||||
var nodeDataArray = [
|
||||
{ key: "Alpha", color: "lightblue" }, // note extra property for each node data: color
|
||||
{ key: "Beta", color: "pink" }
|
||||
];
|
||||
var linkDataArray = [
|
||||
{ from: "Alpha", to: "Beta" }
|
||||
];
|
||||
diagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
|
||||
</pre>
|
||||
<script>goCode("simpleModelWithBind", 250, 150)</script>
|
||||
<p>
|
||||
Now we have the same diagram result as before, but it is implemented in much more general manner.
|
||||
You can easily add more node and link data to build bigger diagrams.
|
||||
And you can easily change the appearance of all of the nodes without modifying the data.
|
||||
</p>
|
||||
<p>
|
||||
Actually, you may notice that the <a>Link</a> is different: it has an arrowhead.
|
||||
No arrowhead was included when we first built this diagram using code.
|
||||
But the default <a>Diagram.linkTemplate</a> includes an arrowhead
|
||||
and we did not replace the link template with a custom one in this example.
|
||||
</p>
|
||||
<p>
|
||||
Notice that the value of <a>Shape.fill</a> in the template above gets a value twice.
|
||||
First it is set to "white". Then the binding sets it to whatever value the node data's "color" property has.
|
||||
It may be useful to be able to specify an initial value that remains in case the node data does
|
||||
not have a "color" property or if there is an error getting that value.
|
||||
</p>
|
||||
<p>
|
||||
At this point we can also be a bit more precise about what a template is.
|
||||
A template is a <a>Part</a> that may have some data <a>Binding</a>s and that is not itself in a diagram
|
||||
but may be copied to create parts that are added to a diagram.
|
||||
</p>
|
||||
|
||||
<h3 id="TemplateDefinitions">Template Definitions</h3>
|
||||
<p>
|
||||
The implementations of all predefined templates are provided in <a href="../extensions/Templates.js">Templates.js</a> in the Extensions directory.
|
||||
You may wish to copy and adapt these definitions when creating your own templates.
|
||||
</p>
|
||||
<p>
|
||||
Those definitions might not be an up-to-date description
|
||||
of the actual standard template implementations that are in <b>GoJS</b>.
|
||||
</p>
|
||||
|
||||
<h2 id="KindsOfModels">Kinds of Models</h2>
|
||||
<p>
|
||||
A model is a way of interpreting a collection of data objects as an abstract graph
|
||||
with various kinds of relationships determined by data properties and the assumptions that the model makes.
|
||||
The simplest kind of model, <a>Model</a>, can only hold "parts" without any relationships between them --
|
||||
no links or groups. But that model class acts as the base class for other kinds of models.
|
||||
</p>
|
||||
<h3 id="GraphLinksModel">GraphLinksModel</h3>
|
||||
<p>
|
||||
The kind of model you have seen above, <a>GraphLinksModel</a>, is actually the most general kind.
|
||||
It supports link relationships using a separate link data object for each <a>Link</a>.
|
||||
There is no inherent limitation on which <a>Nodes</a> a Link may connect, so reflexive and duplicate links are allowed.
|
||||
Links might also result in cycles in the graph.
|
||||
However you may prevent the user from drawing such links by setting various properties, such as <a>Diagram.validCycle</a>.
|
||||
And if you want to have a link appear to connect with a link rather than with a node,
|
||||
this is possible by having special nodes, known as "label nodes", that belong to links and are arranged along the
|
||||
path of a link in the same manner as text labels are arranged on a link.
|
||||
</p>
|
||||
<p>
|
||||
Furthermore a <a>GraphLinksModel</a> also supports identifying logically and physically different connection objects,
|
||||
known as "ports", within a <a>Node</a>.
|
||||
Thus an individual link may connect with a particular port rather than with the node as a whole.
|
||||
The <a href="connectionPoints.html">Link Points</a> and <a href="ports.html">Ports</a> pages discuss this topic in more depth.
|
||||
</p>
|
||||
<p>
|
||||
A <a>GraphLinksModel</a> also supports the group-membership relationship.
|
||||
Any <a>Part</a> can belong to at most one <a>Group</a>; no group can be contained in itself, directly or indirectly.
|
||||
You can learn more about grouping in other pages, such as <a href="groups.html">Groups</a>.
|
||||
</p>
|
||||
<h3 id="TreeModel">TreeModel</h3>
|
||||
<p>
|
||||
A simpler kind of model, the <a>TreeModel</a>, only supports link relationships that form a tree-structured graph.
|
||||
There is no separate link data, so there is no "linkDataArray".
|
||||
The parent-child relationship inherent in trees is determined by an extra property on the child node data which refers to the parent node by its key.
|
||||
If that property, whose name defaults to "parent", is undefined, then that data's corresponding node is a tree root.
|
||||
Each <a>Link</a> is still data bound, but the link's data is the child node data.
|
||||
</p>
|
||||
<pre class="lang-js" id="simpleTree">
|
||||
diagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape,
|
||||
{ figure: "Ellipse" },
|
||||
new go.Binding("fill", "color")),
|
||||
$(go.TextBlock,
|
||||
{ margin: 5 },
|
||||
new go.Binding("text", "key"))
|
||||
);
|
||||
|
||||
var nodeDataArray = [
|
||||
{ key: "Alpha", color: "lightblue" },
|
||||
{ key: "Beta", parent: "Alpha", color: "yellow" }, // note the "parent" property
|
||||
{ key: "Gamma", parent: "Alpha", color: "orange" },
|
||||
{ key: "Delta", parent: "Alpha", color: "lightgreen" }
|
||||
];
|
||||
diagram.model = new go.TreeModel(nodeDataArray);
|
||||
</pre>
|
||||
<script>goCode("simpleTree", 250, 150)</script>
|
||||
<p>
|
||||
Many of the tree-oriented samples make use of a TreeModel instead of a GraphLinksModel.
|
||||
But just because your graph is tree-structured does not mean you have to use a TreeModel.
|
||||
You may find that your data is organized with a separate "table" defining the link relationships,
|
||||
so that using a GraphLinksModel is most natural.
|
||||
Or you may want to use other features that TreeModel does not support.
|
||||
</p>
|
||||
<p>
|
||||
Other pages such as <a href="trees.html">Trees</a> discuss tree-oriented features of <b>GoJS</b> in more detail.
|
||||
</p>
|
||||
|
||||
<h2 id="IdentityAndReferences">Identity and References</h2>
|
||||
<p>
|
||||
Each <a>Node</a> is the visual representation of a specific JavaScript Object that is in the <a>Model.nodeDataArray</a>.
|
||||
If there are two objects in the model, they will result in two nodes, even if the properties of both objects are exactly the same.
|
||||
For example:
|
||||
</p>
|
||||
<pre class="lang-js">
|
||||
myDiagram.model.nodeDataArray = [
|
||||
{ text: "something", count: 17 },
|
||||
{ text: "something", count: 17 }
|
||||
];
|
||||
</pre>
|
||||
<p>
|
||||
This will cause there to be two separate nodes that happen to have the same property values.
|
||||
In fact each of those JavaScript Objects will get a different "key" value, so that references to nodes
|
||||
will always be able to be distinguished.
|
||||
</p>
|
||||
<p>
|
||||
This illustrates how the identity of each node is determined by the Object in memory that is the node's data.
|
||||
You cannot delete a node by removing an object that is similar to one that is in the model.
|
||||
Consider this statement:
|
||||
</p>
|
||||
<pre class="lang-js">
|
||||
myDiagram.model.removeNodeData({ text: "something", count: 17 });
|
||||
</pre>
|
||||
<p>
|
||||
Such code will never remove any node data from the <a>Model.nodeDataArray</a> nor any <a>Node</a> from any <a>Diagram</a>
|
||||
because the Object that is passed to <a>Model.removeNodeData</a> is a new Object, not the <em>same Object</em> that is present in the model.
|
||||
</p>
|
||||
<p>
|
||||
Nor can you find a node by giving it a similar node data object.
|
||||
There is no such method on <a>Model</a>, although there is a <a>Model.findNodeDataForKey</a> method.
|
||||
But if you really want to search for nodes that have particular properties,
|
||||
you can call <a>Diagram.findNodesByExample</a>.
|
||||
</p>
|
||||
<pre class="lang-js">
|
||||
var nodes = myDiagram.findNodesByExample({ text: "something", count: 17 });
|
||||
nodes.each(function(n) { console.log(n.key); });
|
||||
</pre>
|
||||
<p>
|
||||
For the model shown above, this will return a collection of two <a>Node</a>s.
|
||||
It then iterates over that collection and prints each <a>Node.key</a>,
|
||||
which in the case of the above model will be some automatically assigned key values.
|
||||
</p>
|
||||
|
||||
<h3 id="ReferencesToNodes">References to Nodes</h3>
|
||||
<p>
|
||||
Although the identity of a node is the node's data object in the model, references to nodes are not "pointers" to those objects.
|
||||
Instead, references are always by the "key" of the node data.
|
||||
(The property need not be named "key" -- see <a>Model.nodeKeyProperty</a>.)
|
||||
Using keys instead of direct references to data objects makes it easier to read and write models,
|
||||
especially by <a>Model.toJson</a> and <a>Model,fromJson</a>, and to debug them in memory.
|
||||
Thus <a>Link</a>s are defined by data using keys, and <a>Group</a> membership is determined using keys:
|
||||
</p>
|
||||
<pre class="lang-js">
|
||||
myDiagram.model.nodeDataArray = [ // for a GraphLinksModel
|
||||
{ key: "Alpha" },
|
||||
{ key: "Beta", group: "Gamma" },
|
||||
{ key: "Gamma", isGroup: true }
|
||||
];
|
||||
myDiagram.model.linkDataArray = [ // for a GraphLinksModel
|
||||
{ from: "Alpha", to: "Beta"}
|
||||
];
|
||||
</pre>
|
||||
<pre class="lang-js">
|
||||
myDiagram.model.nodeDataArray = [ // for a TreeModel
|
||||
{ key: "Alpha" },
|
||||
{ key: "Beta", parent: "Alpha" }
|
||||
];
|
||||
</pre>
|
||||
|
||||
<h2 id="ModifyingModels">Modifying Models</h2>
|
||||
<p>
|
||||
If you want to add or remove nodes programmatically, you will probably want to call the
|
||||
<a>Model.addNodeData</a> and <a>Model.removeNodeData</a> methods.
|
||||
Use the <a>Model.findNodeDataForKey</a> method to find a particular node data object if you only have its unique key value.
|
||||
You may also call <a>Model.copyNodeData</a> to make a copy of a node data object that you can then modify and pass to <a>Model.addNodeData</a>.
|
||||
</p>
|
||||
<p>
|
||||
It does not work to simply mutate the Array that is the value of <a>Model.nodeDataArray</a>,
|
||||
because the <b>GoJS</b> software will not be notified about any change to any JavaScript Array and
|
||||
thus will not have a chance to add or remove <a>Node</a>s or other <a>Part</a>s as needed.
|
||||
(But setting the <a>Model.nodeDataArray</a> property to refer to a different Array does of course notify the model.)
|
||||
</p>
|
||||
<p>
|
||||
Similarly, it does not work to simply set a property of a node data object.
|
||||
Any <a>Binding</a> that depends on the property will not be notified about any changes,
|
||||
so it will not be able to update its target <a>GraphObject</a> property.
|
||||
For example, setting the color property will not cause the <a>Shape</a> to change color.
|
||||
</p>
|
||||
<pre class="lang-js">
|
||||
var data = myDiagram.model.findNodeDataForKey("Delta");
|
||||
// This will NOT change the color of the "Delta" Node
|
||||
if (data !== null) data.color = "red";
|
||||
</pre>
|
||||
<p>
|
||||
Instead you need to call <a>Model.setDataProperty</a> to modify an object in the model.
|
||||
</p>
|
||||
<pre class="lang-js">
|
||||
var data = myDiagram.model.findNodeDataForKey("Delta");
|
||||
// This will update the color of the "Delta" Node
|
||||
if (data !== null) myDiagram.model.setDataProperty(data, "color", "red");
|
||||
</pre>
|
||||
<p>
|
||||
Calling model methods such as <a>Model.addNodeData</a> or <a>Model.setDataProperty</a> is required
|
||||
when the JavaScript Array or Object is already part of the Model.
|
||||
When first building the Array of Objects for the <a>Model.nodeDataArray</a>
|
||||
or when initializing a JavaScript Object as a new node data object, such calls are not necessary.
|
||||
But once the data is part of the Model, calling the model's methods to effect changes is necessary.
|
||||
</p>
|
||||
|
||||
<h3 id="ExternallyModifiedData">Externally Modified Data</h3>
|
||||
<p>
|
||||
In some software architectures it might not be possible to insist that all data changes go through <a>Model</a> methods.
|
||||
In such cases it is possible to call <a>Diagram.updateAllRelationshipsFromData</a> and
|
||||
<a>Diagram.updateAllTargetBindings</a>.
|
||||
</p>
|
||||
<p>
|
||||
However, please note that doing so will prevent the <a>UndoManager</a> from properly recording state changes.
|
||||
There would be no way for the <a>UndoManager</a> to know what had been the previous values of properties.
|
||||
Furthermore it makes it hard to have more than one Diagram showing the Model.
|
||||
</p>
|
||||
|
||||
<h3 id="ImmutableData">Immutable Data</h3>
|
||||
<p>
|
||||
In some software architectures it is customary to have "models" consist of immutable (unmodifiable) data.
|
||||
However, as the GoJS diagram is modified, its model data will be modified, so you cannot use that immutable data in the model.
|
||||
You could make a copy of all of the immutable data and then replace the <a>Diagram.model</a> whenever the data
|
||||
has changed outside of the diagram/model. But that would cause old Nodes and Links to be re-created,
|
||||
and that would be unworkably expensive in time and space when the model is large.
|
||||
</p>
|
||||
<p>
|
||||
If you do have immutable model data, you can update the existing <a>Model</a> and thus its <a>Diagram</a>s by calling
|
||||
the <a>Model.mergeNodeDataArray</a> and <a>GraphLinksModel.mergeLinkDataArray</a> methods.
|
||||
This will be much more efficient than replacing the <a>Model.nodeDataArray</a> and <a>GraphLinksModel.linkDataArray</a>
|
||||
Arrays each time, because it will preserve the existing Nodes and Links if possible.
|
||||
</p>
|
||||
<p>
|
||||
Note that this scheme depends on maintaining the "key"s for all of the node data and for all of the link data.
|
||||
That happens automatically for all nodes, but for GraphLinksModels, it means setting
|
||||
<a>GraphLinksModel.linkKeyProperty</a> to the name of the property on the link data that
|
||||
you want to use to remember the key value.
|
||||
</p>
|
||||
<p>
|
||||
After each diagram transaction some of the model data may have changed.
|
||||
But you cannot share references to that modified data with the rest of the software that is expecting immutable data.
|
||||
Instead you can call <a>Model.toIncrementalData</a> which will provide copies of the modified data.
|
||||
That data can then be used to update the rest of the app's state.
|
||||
Read more about this at <a href="react.html">Using GoJS with React</a>
|
||||
and the <a href="https://github.com/NorthwoodsSoftware/gojs-react">gojs-react package</a>,
|
||||
which provides generic Diagram components that you can use in your app using React.
|
||||
</p>
|
||||
|
||||
<h2 id="SavingAndLoadingModels">Saving and Loading Models</h2>
|
||||
<p>
|
||||
<b>GoJS</b> does not require you to save models in any particular medium or format.
|
||||
But because this is JavaScript and JSON is the most popular data-interchange format,
|
||||
we do make it easy to write and read models as text in JSON format.
|
||||
</p>
|
||||
<p>
|
||||
Just call <a>Model.toJson</a> to generate a string representing your model.
|
||||
Call the static method <a>Model,fromJson</a> to construct and initialize a model given a string produced by <a>Model.toJson</a>.
|
||||
Many of the samples demonstrate this -- search for JavaScript functions named "save" and "load".
|
||||
Most of those functions write and read a TextArea on the page itself, so that you can see and modify the JSON text and then load it to get a new diagram.
|
||||
But please be cautious when editing because JSON syntax is very strict, and any syntax errors will cause those "load" functions to fail.
|
||||
</p>
|
||||
<p>
|
||||
JSON formatted text has strict limits on the kinds of data that you can represent without additional assumptions.
|
||||
To save and load any data properties that you set on your node data (or link data), they need to meet the following requirements:
|
||||
</p>
|
||||
<ul>
|
||||
<li>the property is enumerable and its name does not start with an underscore (you can use property names that do start with an underscore, but they won't be saved)</li>
|
||||
<li>the property value is not undefined and is not a function (JSON cannot faithfully hold functions)</li>
|
||||
<li>the model knows how to convert the property value to JSON format (numbers, strings, JavaScript Arrays, or plain JavaScript Objects)</li>
|
||||
<li>property values that are Objects or Arrays form a tree structure -- no shared or cyclical references</li>
|
||||
</ul>
|
||||
<p>
|
||||
<a>Model.toJson</a> and <a>Model,fromJson</a> will also handle instances of
|
||||
<a>Point</a>, <a>Size</a>, <a>Rect</a>, <a>Spot</a>, <a>Margin</a>, <a>Geometry</a>, and non-pattern <a>Brush</a>es.
|
||||
However we recommend that you store those objects in their string representations, using those classes' <code>parse</code> and <code>stringify</code> static functions.
|
||||
</p>
|
||||
<p>
|
||||
Because you are using JavaScript, it is trivial for you to add data properties to your node data.
|
||||
This allows you to associate whatever information you need with each node.
|
||||
But if you need to associate some information with the model, which will be present even if there is no node data at all,
|
||||
you can add properties to the <a>Model.modelData</a> object.
|
||||
This object's properties will be written by <a>Model.toJson</a> and read by <a>Model,fromJson</a>, just as node data objects are written and read.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user