UNPKG

32.3 kBHTMLView Raw
1<!DOCTYPE html>
2<html lang="en">
3 <head>
4<meta charset="utf-8"/>
5<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, viewport-fit=cover"/>
6
7<link rel="stylesheet" href="../assets/css/style.css"/>
8<!-- Copyright 1998-2021 by Northwoods Software Corporation. --> <title> GoJS and React -- Northwoods Software </title>
9 <link rel="stylesheet" href="../assets/css/prism.css" />
10 </head>
11 <script>
12
13 window.diagrams = [];
14 window.goCode = function(pre, w, h, parentid, animation) {
15 window.diagrams.push([pre, w, h, parentid, animation]);
16 }
17 </script>
18 <body>
19 <nav id="navTop" class="w-full z-30 top-0 text-white bg-nwoods-primary">
20 <div class="w-full container max-w-screen-lg mx-auto flex flex-wrap sm:flex-nowrap items-center justify-between mt-0 py-2">
21 <div class="md:pl-4">
22 <a class="text-white hover:text-white no-underline hover:no-underline
23 font-bold text-2xl lg:text-4xl rounded-lg hover:bg-nwoods-secondary " href="../">
24 <h1 class="mb-0 p-1 ">GoJS</h1>
25 </a>
26 </div>
27 <button id="topnavButton" class="rounded-lg sm:hidden focus:outline-none focus:ring" aria-label="Navigation">
28 <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
29 <path id="topnavOpen" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z" clip-rule="evenodd"></path>
30 <path id="topnavClosed" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
31 </svg>
32 </button>
33 <div id="topnavList" class="hidden sm:block items-center w-auto mt-0 text-white p-0 z-20">
34 <ul class="list-reset list-none font-semibold flex justify-end flex-wrap sm:flex-nowrap items-center px-0 pb-0">
35 <li class="p-1 sm:p-0"><a class="topnav-link" href="../learn/">Learn</a></li>
36 <li class="p-1 sm:p-0"><a class="topnav-link" href="../samples/">Samples</a></li>
37 <li class="p-1 sm:p-0"><a class="topnav-link" href="../intro/">Intro</a></li>
38 <li class="p-1 sm:p-0"><a class="topnav-link" href="../api/">API</a></li>
39 <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/products/register.html">Register</a></li>
40 <li class="p-1 sm:p-0"><a class="topnav-link" href="../download.html">Download</a></li>
41 <li class="p-1 sm:p-0"><a class="topnav-link" href="https://forum.nwoods.com/c/gojs/11">Forum</a></li>
42 <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/contact.html"
43 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a></li>
44 <li class="p-1 sm:p-0"><a class="topnav-link" href="https://www.nwoods.com/sales/index.html"
45 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a></li>
46 </ul>
47 </div>
48 </div>
49 <hr class="border-b border-gray-600 opacity-50 my-0 py-0" />
50 </nav>
51
52 <div class="md:flex flex-col md:flex-row md:min-h-screen w-full max-w-screen-xl mx-auto">
53
54 <div id="navSide" class="flex flex-col w-full md:w-40 lg:w-48 text-gray-700 bg-white flex-shrink-0">
55 <div class="flex-shrink-0 px-8 py-4">
56 <button id="navButton" class="rounded-lg md:hidden focus:outline-none focus:ring" aria-label="Navigation">
57 <svg fill="currentColor" viewBox="0 0 20 20" class="w-6 h-6">
58 <path id="navOpen" fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM9 15a1 1 0 011-1h6a1 1 0 110 2h-6a1 1 0 01-1-1z" clip-rule="evenodd"></path>
59 <path id="navClosed" class="hidden" fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
60 </svg>
61 </button>
62 </div>
63 <nav id="navList" class="min-h-screen hidden md:block sidebar-nav flex-grow px-1 lg:px-4 pb-4 md:pb-0 md:overflow-y-auto break-words">
64 <a href="index.html">Basics</a>
65 <a href="buildingObjects.html">Building Parts</a>
66 <a href="usingModels.html">Using Models</a>
67 <a href="dataBinding.html">Data Binding</a>
68 <a href="react.html">GoJS with React</a>
69 <a href="angular.html">GoJS with Angular</a>
70 <a href="textBlocks.html">TextBlocks</a>
71 <a href="shapes.html">Shapes</a>
72 <a href="pictures.html">Pictures</a>
73 <a href="panels.html">Panels</a>
74 <a href="tablePanels.html">Table Panels</a>
75 <a href="brush.html">Brushes</a>
76 <a href="sizing.html">Sizing Objects</a>
77 <a href="itemArrays.html">Item Arrays</a>
78 <a href="changedEvents.html">Changed Events</a>
79 <a href="transactions.html">Transactions</a>
80 <a href="viewport.html">Coordinates</a>
81 <a href="initialView.html">Initial View</a>
82 <a href="collections.html">Collections</a>
83 <a href="links.html">Links</a>
84 <a href="linkLabels.html">Link Labels</a>
85 <a href="connectionPoints.html">Link Points</a>
86 <a href="ports.html">Ports</a>
87 <a href="nodes.html">Nodes</a>
88 <a href="debugging.html">Debugging</a>
89 <a href="layouts.html">Layouts</a>
90 <a href="trees.html">Trees</a>
91 <a href="subtrees.html">SubTrees</a>
92 <a href="groups.html">Groups</a>
93 <a href="subgraphs.html">SubGraphs</a>
94 <a href="sizedGroups.html">Sized Groups</a>
95 <a href="selection.html">Selection</a>
96 <a href="highlighting.html">Highlighting</a>
97 <a href="animation.html">Animation</a>
98 <a href="toolTips.html">ToolTips</a>
99 <a href="contextmenus.html">Context Menus</a>
100 <a href="events.html">Diagram Events</a>
101 <a href="tools.html">Tools</a>
102 <a href="commands.html">Commands</a>
103 <a href="permissions.html">Permissions</a>
104 <a href="validation.html">Validation</a>
105 <a href="HTMLInteraction.html">HTML Interaction</a>
106 <a href="layers.html">Layers &amp; Z-ordering</a>
107 <a href="palette.html">Palette</a>
108 <a href="overview.html">Overview</a>
109 <a href="resizing.html">Resizing Diagrams</a>
110 <a href="replacingDeleting.html">Replacing and Deleting</a>
111 <a href="buttons.html">Buttons</a>
112 <a href="templateMaps.html">Template Maps</a>
113 <a href="legends.html">Legends and Titles</a>
114 <a href="extensions.html">Extensions</a>
115 <a href="geometry.html">Geometry Strings</a>
116 <a href="grids.html">Grid Patterns</a>
117 <a href="graduatedPanels.html">Graduated Panels</a>
118 <a href="makingImages.html">Diagram Images</a>
119 <a href="makingSVG.html">Diagram SVG</a>
120 <a href="printing.html">Printing</a>
121 <a href="serverSideImages.html">Server-side Images</a>
122 <a href="nodeScript.html">GoJS in Node.js</a>
123 <a href="testing.html">Testing</a>
124 <a href="storage.html">Storage</a>
125 <a href="performance.html">Performance</a>
126 <a href="source.html">Building from Source</a>
127 <a href="platforms.html">Platforms</a>
128 <a href="deployment.html">Deployment</a>
129 </nav>
130 </div>
131 <div class="pt-4 px-2 md:px-0 lg:px-4 pb-16 w-full overflow-hidden">
132
133
134
135
136<h1>Using GoJS with React</h1>
137<p class="box" style="background-color: lightgoldenrodyellow;">
138 Examples of most of the topics discussed on this page can be found in the <a href="https://github.com/NorthwoodsSoftware/gojs-react-basic" target="_blank">gojs-react-basic</a> project,
139 which serves as a simple starter project.
140</p>
141
142<p>
143 If you are new to GoJS, it may be helpful to first visit the <a href="../learn/index.html" target="_blank">Getting Started Tutorial</a>.
144</p>
145
146<p>
147 The easiest way to get a component set up for a GoJS Diagram is to use the <a href="https://github.com/NorthwoodsSoftware/gojs-react" target="_blank">gojs-react</a> package,
148 which exports React Components for GoJS Diagrams, Palettes, and Overviews.
149 The <a href="https://github.com/NorthwoodsSoftware/gojs-react-basic" target="_blank">gojs-react-basic</a> project demonstrates how to use these components.
150 More information about the package, including the various props it takes, can be found on the <a href="https://github.com/NorthwoodsSoftware/gojs-react" target="_blank">Github</a> or
151 <a href="https://npmjs.com/gojs-react" target="_blank">NPM</a> pages. Our examples will be using a <a>GraphLinksModel</a>, but any model can be used.
152</p>
153
154<h2 id="quickstart">Quick start with an existing React application</h2>
155<h4 id="Installation">Installation</h4>
156<p>
157 Start by installing GoJS and gojs-react: <code>npm install gojs gojs-react</code>.
158</p>
159<h4 id="DiagramStyling">Diagram styling</h4>
160<p>
161 Next, set up a CSS class for the GoJS diagram's div:
162</p>
163<pre class="lang-css"><code>
164 /* App.css */
165 .diagram-component {
166 width: 400px;
167 height: 400px;
168 border: solid 1px black;
169 background-color: white;
170 }
171</code></pre>
172<h4 id="RenderingComponent">Rendering the component</h4>
173<p>
174 Finally, add an initDiagram function and a model change handler function, and add the ReactDiagram component inside your render method.
175 Note that the UndoManager should always be enabled to allow for transactions to take place,
176 but the <a>UndoManager.maxHistoryLength</a> can be set to 0 to prevent undo and redo.
177</p>
178<pre class="lang-js"><code>
179 // App.js
180 import React from 'react';
181
182 import * as go from 'gojs';
183 import { ReactDiagram } from 'gojs-react';
184
185 import './App.css'; // contains .diagram-component CSS
186
187 // ...
188
189 /**
190 * Diagram initialization method, which is passed to the ReactDiagram component.
191 * This method is responsible for making the diagram and initializing the model and any templates.
192 * The model's data should not be set here, as the ReactDiagram component handles that via the other props.
193 */
194 function initDiagram() {
195 const $ = go.GraphObject.make;
196 // set your license key here before creating the diagram: go.Diagram.licenseKey = "...";
197 const diagram =
198 $(go.Diagram,
199 {
200 'undoManager.isEnabled': true, // must be set to allow for model change listening
201 // 'undoManager.maxHistoryLength': 0, // uncomment disable undo/redo functionality
202 'clickCreatingTool.archetypeNodeData': { text: 'new node', color: 'lightblue' },
203 model: $(go.GraphLinksModel,
204 {
205 linkKeyProperty: 'key' // IMPORTANT! must be defined for merges and data sync when using GraphLinksModel
206 })
207 });
208
209 // define a simple Node template
210 diagram.nodeTemplate =
211 $(go.Node, 'Auto', // the Shape will go around the TextBlock
212 new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
213 $(go.Shape, 'RoundedRectangle',
214 { name: 'SHAPE', fill: 'white', strokeWidth: 0 },
215 // Shape.fill is bound to Node.data.color
216 new go.Binding('fill', 'color')),
217 $(go.TextBlock,
218 { margin: 8, editable: true }, // some room around the text
219 new go.Binding('text').makeTwoWay()
220 )
221 );
222
223 return diagram;
224 }
225
226 /**
227 * This function handles any changes to the GoJS model.
228 * It is here that you would make any updates to your React state, which is dicussed below.
229 */
230 function handleModelChange(changes) {
231 alert('GoJS model changed!');
232 }
233
234 // render function...
235 function App() {
236 return (
237 &lt;div&gt;
238 ...
239 &lt;ReactDiagram
240 initDiagram={initDiagram}
241 divClassName='diagram-component'
242 nodeDataArray={[
243 { key: 0, text: 'Alpha', color: 'lightblue', loc: '0 0' },
244 { key: 1, text: 'Beta', color: 'orange', loc: '150 0' },
245 { key: 2, text: 'Gamma', color: 'lightgreen', loc: '0 150' },
246 { key: 3, text: 'Delta', color: 'pink', loc: '150 150' }
247 ]}
248 linkDataArray={[
249 { key: -1, from: 0, to: 1 },
250 { key: -2, from: 0, to: 2 },
251 { key: -3, from: 1, to: 1 },
252 { key: -4, from: 2, to: 3 },
253 { key: -5, from: 3, to: 0 }
254 ]}
255 onModelChange={handleModelChange}
256 /&gt;
257 ...
258 &lt;/div&gt;
259 );
260 }
261</code></pre>
262<p>
263 That's it! You should now have a GoJS diagram rendering within your React application.
264 Try editing the text of a node or deleting a node, and you'll see an alert on the page.
265</p>
266
267<h2 id="stateful">Usage in a stateful React app</h2>
268<p>
269 Typically the data being passed to the ReactDiagram component will be used elsewhere in your app and will exist in React state.
270 For example, you may have some kind of inspector that can be used to modify node properties, and therefore the state should be lifted up and held by a parent component
271 of both the diagram and the inspector.
272</p>
273<p>
274 A basic setup can be seen in the <a href="https://github.com/NorthwoodsSoftware/gojs-react-basic" target="_blank">gojs-react-basic</a> project,
275 but we'll describe some of the methodology here.
276</p>
277<h4 id="CreatingWrapperComponent">Creating a wrapper component</h4>
278<p>
279 When handling state, it is often useful to write a wrapper component around the gojs-react components to pass the necessary props along and keep GoJS initialization out of the main app.
280 There are a few things that should be set up in the wrapper component:
281 <ul>
282 <li>a set of props coming in from the parent component which holds state and handlers</li>
283 <li>a ref to the ReactDiagram component so getDiagram() and clear() can be used</li>
284 <li>componentDidMount and componentWillUnmount methods to add/remove app-specific diagram listeners</li>
285 <li>an initDiagram method to be passed to the ReactDiagram component</li>
286 </ul>
287 Node and link data are <i>merged</i> into the GoJS model, thus properties should not be removed from node or link data,
288 but rather set to undefined if they are no longer needed; GoJS avoids destructive merging.
289</p>
290<p>
291 Below, we'll pass linkDataArray and modelData as props to the ReactDiagram, but note that they are not always needed in gojs-react components,
292 so your app may not need to include them. For proper initial loading of data, one should have the data ready before the ReactDiagram component mounts.
293 This allows layouts and linking to occur properly with the initial data set.
294</p>
295<pre class="lang-js"><code>
296 import * as go from 'gojs';
297 import { ReactDiagram } from 'gojs-react';
298 import * as React from 'react';
299
300 // props passed in from a parent component holding state, some of which will be passed to ReactDiagram
301 interface WrapperProps {
302 nodeDataArray: Array&lt;go.ObjectData&gt;;
303 linkDataArray: Array&lt;go.ObjectData&gt;;
304 modelData: go.ObjectData;
305 skipsDiagramUpdate: boolean;
306 onDiagramEvent: (e: go.DiagramEvent) => void;
307 onModelChange: (e: go.IncrementalData) => void;
308 }
309
310 export class DiagramWrapper extends React.Component&lt;WrapperProps, {}&gt; {
311 /**
312 * Ref to keep a reference to the component, which provides access to the GoJS diagram via getDiagram().
313 */
314 private diagramRef: React.RefObject&lt;ReactDiagram&gt;;
315
316 constructor(props: WrapperProps) {
317 super(props);
318 this.diagramRef = React.createRef();
319 }
320
321 /**
322 * Get the diagram reference and add any desired diagram listeners.
323 * Typically the same function will be used for each listener,
324 * with the function using a switch statement to handle the events.
325 * This is only necessary when you want to define additional app-specific diagram listeners.
326 */
327 public componentDidMount() {
328 if (!this.diagramRef.current) return;
329 const diagram = this.diagramRef.current.getDiagram();
330 if (diagram instanceof go.Diagram) {
331 diagram.addDiagramListener('ChangedSelection', this.props.onDiagramEvent);
332 }
333 }
334
335 /**
336 * Get the diagram reference and remove listeners that were added during mounting.
337 * This is only necessary when you have defined additional app-specific diagram listeners.
338 */
339 public componentWillUnmount() {
340 if (!this.diagramRef.current) return;
341 const diagram = this.diagramRef.current.getDiagram();
342 if (diagram instanceof go.Diagram) {
343 diagram.removeDiagramListener('ChangedSelection', this.props.onDiagramEvent);
344 }
345 }
346
347 /**
348 * Diagram initialization method, which is passed to the ReactDiagram component.
349 * This method is responsible for making the diagram and initializing the model, any templates,
350 * and maybe doing other initialization tasks like customizing tools.
351 * The model's data should not be set here, as the ReactDiagram component handles that via the other props.
352 */
353 private initDiagram(): go.Diagram {
354 const $ = go.GraphObject.make;
355 // set your license key here before creating the diagram: go.Diagram.licenseKey = "...";
356 const diagram =
357 $(go.Diagram,
358 {
359 'undoManager.isEnabled': true, // must be set to allow for model change listening
360 // 'undoManager.maxHistoryLength': 0, // uncomment disable undo/redo functionality
361 'clickCreatingTool.archetypeNodeData': { text: 'new node', color: 'lightblue' },
362 model: $(go.GraphLinksModel,
363 {
364 linkKeyProperty: 'key', // IMPORTANT! must be defined for merges and data sync when using GraphLinksModel
365 // positive keys for nodes
366 makeUniqueKeyFunction: (m: go.Model, data: any) => {
367 let k = data.key || 1;
368 while (m.findNodeDataForKey(k)) k++;
369 data.key = k;
370 return k;
371 },
372 // negative keys for links
373 makeUniqueLinkKeyFunction: (m: go.GraphLinksModel, data: any) => {
374 let k = data.key || -1;
375 while (m.findLinkDataForKey(k)) k--;
376 data.key = k;
377 return k;
378 }
379 })
380 });
381
382 // define a simple Node template
383 diagram.nodeTemplate =
384 $(go.Node, 'Auto', // the Shape will go around the TextBlock
385 new go.Binding('location', 'loc', go.Point.parse).makeTwoWay(go.Point.stringify),
386 $(go.Shape, 'RoundedRectangle',
387 {
388 name: 'SHAPE', fill: 'white', strokeWidth: 0,
389 // set the port properties:
390 portId: '', fromLinkable: true, toLinkable: true, cursor: 'pointer'
391 },
392 // Shape.fill is bound to Node.data.color
393 new go.Binding('fill', 'color')),
394 $(go.TextBlock,
395 { margin: 8, editable: true, font: '400 .875rem Roboto, sans-serif' }, // some room around the text
396 new go.Binding('text').makeTwoWay()
397 )
398 );
399
400 // relinking depends on modelData
401 diagram.linkTemplate =
402 $(go.Link,
403 new go.Binding('relinkableFrom', 'canRelink').ofModel(),
404 new go.Binding('relinkableTo', 'canRelink').ofModel(),
405 $(go.Shape),
406 $(go.Shape, { toArrow: 'Standard' })
407 );
408
409 return diagram;
410 }
411
412 public render() {
413 return (
414 &lt;ReactDiagram
415 ref={this.diagramRef}
416 divClassName='diagram-component'
417 initDiagram={this.initDiagram}
418 nodeDataArray={this.props.nodeDataArray}
419 linkDataArray={this.props.linkDataArray}
420 modelData={this.props.modelData}
421 onModelChange={this.props.onModelChange}
422 skipsDiagramUpdate={this.props.skipsDiagramUpdate}
423 /&gt;
424 );
425 }
426 }
427</code></pre>
428<h4 id="UsingWrapperComponentWithinApp">Using the wrapper component within the app</h4>
429<p>
430 The application should set up a few things to be passed to the wrapper described above:
431 <ul>
432 <li>state containing a nodeDataArray, linkDataArray, modelData object, and skipsDiagramUpdate flag</li>
433 <li>a handleDiagramEvent method for any app-specific DiagramEvents, such as 'ChangedSelection'</li>
434 <li>a handleModelChange method for updating state based on updates from the GoJS model</li>
435 </ul>
436</p>
437<pre class="lang-js"><code>
438 import * as go from 'gojs';
439 import * as React from 'react';
440
441 import { DiagramWrapper } from './components/Diagram';
442
443 interface AppState {
444 // ...
445 nodeDataArray: Array&lt;go.ObjectData&gt;;
446 linkDataArray: Array&lt;go.ObjectData&gt;;
447 modelData: go.ObjectData;
448 selectedKey: number | null;
449 skipsDiagramUpdate: boolean;
450 }
451
452 class App extends React.Component&lt;{}, AppState&gt; {
453 constructor(props: object) {
454 super(props);
455 this.state = {
456 // ...
457 nodeDataArray: [
458 { key: 0, text: 'Alpha', color: 'lightblue', loc: '0 0' },
459 { key: 1, text: 'Beta', color: 'orange', loc: '150 0' },
460 { key: 2, text: 'Gamma', color: 'lightgreen', loc: '0 150' },
461 { key: 3, text: 'Delta', color: 'pink', loc: '150 150' }
462 ],
463 linkDataArray: [
464 { key: -1, from: 0, to: 1 },
465 { key: -2, from: 0, to: 2 },
466 { key: -3, from: 1, to: 1 },
467 { key: -4, from: 2, to: 3 },
468 { key: -5, from: 3, to: 0 }
469 ],
470 modelData: {
471 canRelink: true
472 },
473 selectedKey: null,
474 skipsDiagramUpdate: false
475 };
476 // bind handler methods
477 this.handleDiagramEvent = this.handleDiagramEvent.bind(this);
478 this.handleModelChange = this.handleModelChange.bind(this);
479 this.handleRelinkChange = this.handleRelinkChange.bind(this);
480 }
481
482 /**
483 * Handle any app-specific DiagramEvents, in this case just selection changes.
484 * On ChangedSelection, find the corresponding data and set the selectedKey state.
485 *
486 * This is not required, and is only needed when handling DiagramEvents from the GoJS diagram.
487 * @param e a GoJS DiagramEvent
488 */
489 public handleDiagramEvent(e: go.DiagramEvent) {
490 const name = e.name;
491 switch (name) {
492 case 'ChangedSelection': {
493 const sel = e.subject.first();
494 if (sel) {
495 this.setState({ selectedKey: sel.key });
496 } else {
497 this.setState({ selectedKey: null });
498 }
499 break;
500 }
501 default: break;
502 }
503 }
504
505 /**
506 * Handle GoJS model changes, which output an object of data changes via Model.toIncrementalData.
507 * This method should iterates over those changes and update state to keep in sync with the GoJS model.
508 * This can be done via setState in React or another preferred state management method.
509 * @param obj a JSON-formatted string
510 */
511 public handleModelChange(obj: go.IncrementalData) {
512 const insertedNodeKeys = obj.insertedNodeKeys;
513 const modifiedNodeData = obj.modifiedNodeData;
514 const removedNodeKeys = obj.removedNodeKeys;
515 const insertedLinkKeys = obj.insertedLinkKeys;
516 const modifiedLinkData = obj.modifiedLinkData;
517 const removedLinkKeys = obj.removedLinkKeys;
518 const modifiedModelData = obj.modelData;
519
520 console.log(obj);
521
522 // see gojs-react-basic for an example model change handler
523 // when setting state, be sure to set skipsDiagramUpdate: true since GoJS already has this update
524 }
525
526 /**
527 * Handle changes to the checkbox on whether to allow relinking.
528 * @param e a change event from the checkbox
529 */
530 public handleRelinkChange(e: any) {
531 const target = e.target;
532 const value = target.checked;
533 this.setState({ modelData: { canRelink: value }, skipsDiagramUpdate: false });
534 }
535
536 public render() {
537 let selKey;
538 if (this.state.selectedKey !== null) {
539 selKey = &lt;p&gt;Selected key: {this.state.selectedKey}&lt;/p&gt;;
540 }
541
542 return (
543 &lt;div&gt;
544 &lt;DiagramWrapper
545 nodeDataArray={this.state.nodeDataArray}
546 linkDataArray={this.state.linkDataArray}
547 modelData={this.state.modelData}
548 skipsDiagramUpdate={this.state.skipsDiagramUpdate}
549 onDiagramEvent={this.handleDiagramEvent}
550 onModelChange={this.handleModelChange}
551 /&gt;
552 &lt;label&gt;
553 Allow Relinking?
554 &lt;input
555 type='checkbox'
556 id='relink'
557 checked={this.state.modelData.canRelink}
558 onChange={this.handleRelinkChange} /&gt;
559 &lt;/label&gt;
560 {selKey}
561 &lt;/div&gt;
562 );
563 }
564 }
565</code></pre>
566<h4>A Note on Diagram Reinitialization</h4>
567<p>
568 Occasionally you may want to treat a model update as if you were loading a completely new model.
569 But initialization is done via the initDiagram function, within the componentDidMount lifecycle method, and only once.
570 A regular model update is not treated as an initialization, so none of the <b>initial...</b> properties
571 of your Diagram will apply.
572</p>
573<p>
574 To address this problem, ReactDiagram exposes a clear() method.
575 When called, it clears its diagram of all nodes, links, and model data, and
576 prepares the next state update to be treated as a diagram initialization.
577 That will result in an initial layout and perform initial diagram content alignment and scaling.
578 Note that the initDiagram function is not called again.
579</p>
580<p>
581 Here is a small sample of how one might trigger diagram reinitilization using the clear() method.
582</p>
583<pre class="lang-js"><code>
584 public reinitModel() {
585 this.diagramRef.current.clear();
586 this.setState({
587 nodeDataArray: [
588 { key: 0, text: 'Epsilon', color: 'lightblue' },
589 { key: 1, text: 'Zeta', color: 'orange' },
590 { key: 2, text: 'Eta', color: 'lightgreen' },
591 { key: 3, text: 'Theta', color: 'pink' }
592 ],
593 linkDataArray: [
594 { key: -1, from: 0, to: 1 },
595 { key: -2, from: 0, to: 2 },
596 { key: -3, from: 1, to: 1 },
597 { key: -4, from: 2, to: 3 },
598 { key: -5, from: 3, to: 0 }
599 ],
600 skipsDiagramUpdate: false
601 });
602 }
603</code></pre>
604<p>
605 These are the basics for setting up GoJS within a React application. See <a href="https://github.com/NorthwoodsSoftware/gojs-react-basic" target="_blank">gojs-react-basic</a>
606 for a working example and the <a href="https://github.com/NorthwoodsSoftware/gojs-react" target="_blank">gojs-react</a> Github page for further explanation of various props
607 passed to the components.
608</p>
609 </div>
610 </div>
611
612 <div class="bg-nwoods-primary">
613 <section class="max-w-screen-lg text-white container mx-auto py-2 px-12">
614 <p id="version" class="leading-none mb-2 my-4">GoJS</p>
615 </section>
616 </div><footer class="bg-nwoods-primary text-white">
617 <div class="container max-w-screen-lg mx-auto px-8">
618 <div class="w-full py-6">
619
620 <div class="max-w-screen-lg xl:max-w-screen-xl mx-auto px-4 sm:px-6 md:px-8">
621 <ul class="text-sm font-medium pb-14 sm:pb-20 grid grid-cols-1 sm:grid-cols-3 gap-y-10">
622 <li class="list-none row-span-2">
623 <h2 class="text-base font-semibold tracking-wide">GoJS</h2>
624 <ul class="list-none space-y-4 md:space-y-1 px-0">
625 <li>
626 <a href="../samples/index.html">Samples</a>
627 </li>
628 <li>
629 <a href="../learn/index.html">Learn</a>
630 </li>
631 <li>
632 <a href="../intro/index.html">Intro</a>
633 </li>
634 <li>
635 <a href="../api/index.html">API</a>
636 </li>
637 <li>
638 <a href="../changelog.html">Changelog</a>
639 </li>
640 <li>
641 <a href="https://github.com/NorthwoodsSoftware/GoJS">GitHub</a>
642 </li>
643 </ul>
644 </li>
645 <li class="list-none row-span-2">
646 <h2 class="text-base font-semibold tracking-wide">Support</h2>
647 <ul class="list-none space-y-4 md:space-y-1 px-0">
648 <li>
649 <a href="https://www.nwoods.com/contact.html"
650 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a>
651 </li>
652 <li>
653 <a href="https://forum.nwoods.com/c/gojs">Forum</a>
654 </li>
655 <li>
656 <a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a>
657 </li>
658 <li>
659 <a href="https://www.nwoods.com/sales/index.html"
660 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a>
661 </li>
662 <li>
663 <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">Videos</a>
664 </li>
665 </ul>
666 </li>
667 <li class="list-none row-span-2">
668 <h2 class="text-base font-semibold tracking-wide">Company</h2>
669 <ul class="list-none space-y-4 md:space-y-1 px-0">
670 <li>
671 <a href="https://www.nwoods.com">Northwoods</a>
672 </li>
673 <li>
674 <a href="https://www.nwoods.com/about.html">About Us</a>
675 </li>
676 <li>
677 <a href="https://www.nwoods.com/contact.html">Contact Us</a>
678 </li>
679 <li>
680 <a href="https://twitter.com/northwoodsgo">Twitter</a>
681 </li>
682
683 </ul>
684 </li>
685 </ul>
686
687
688 <p class="text-sm text-gray-100 md:mb-6">
689 Copyright 1998-2021 <a class="text-white" href="https://www.nwoods.com">Northwoods Software</a>
690 </p>
691 </div>
692 </div>
693</footer> </body>
694
695<script async src="https://www.googletagmanager.com/gtag/js?id=UA-1506307-5"></script>
696<script>
697 window.dataLayer = window.dataLayer || [];
698 function gtag(){dataLayer.push(arguments);}
699 gtag('js', new Date()); gtag('config', 'UA-1506307-5');
700 var getOutboundLink = function(url, label) {
701 gtag('event', 'click', {
702 'event_category': 'outbound',
703 'event_label': label,
704 'transport_type': 'beacon'
705 });
706 }
707
708 // topnav
709 var topButton = document.getElementById("topnavButton");
710 var topnavList = document.getElementById("topnavList");
711 topButton.addEventListener("click", function() {
712 this.classList.toggle("active");
713 topnavList.classList.toggle("hidden");
714 document.getElementById("topnavOpen").classList.toggle("hidden");
715 document.getElementById("topnavClosed").classList.toggle("hidden");
716 });
717</script>
718 <script src="../assets/js/prism.js"></script>
719 <script src="../release/go.js"></script>
720 <script src="../assets/js/goDoc.js"></script>
721 <script>
722 document.addEventListener("DOMContentLoaded", function() {
723 if (window.go) document.getElementById('version').textContent = "GoJS version " + go.version;
724 if (window.goDoc) window.goDoc();
725 var d = window.diagrams;
726 for (var i = 0; i < d.length; i++) {
727 var dargs = d[i];
728 goCodeExecute(dargs[0], dargs[1], dargs[2], dargs[3], dargs[4]);
729 }
730 if (window.extra) window.extra();
731 });
732 </script>
733</html>