UNPKG

30.8 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 Item Arrays-- 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<h1>Panel Item Arrays</h1>
134<p>
135How does one display a variable number of elements in a node by data binding to a JavaScript Array?
136The answer is simple: just bind (or set) <a>Panel.itemArray</a>.
137The <a>Panel</a> will contain as many elements as there are values in the bound Array.
138</p>
139<p>
140See samples that make use of item Arrays in the <a href="../samples/index.html#itemarrays">samples index</a>.
141</p>
142
143<h2 id="SimpleItemLists">Simple item lists</h2>
144<p>
145Here is a very simple example demonstrating the standard way of binding <a>Panel.itemArray</a> to a data property whose value is an Array.
146</p>
147<pre class="lang-js" id="simple"><code>
148 diagram.nodeTemplate =
149 $(go.Node, "Vertical",
150 new go.Binding("itemArray", "items"));
151
152 diagram.model =
153 $(go.GraphLinksModel,
154 {
155 nodeDataArray: [
156 { key: 1, items: [ "Alpha", "Beta", "Gamma", "Delta" ] },
157 { key: 2, items: [ "first", "second", "third" ] }
158 ],
159 linkDataArray: [
160 { from: 1, to: 2 }
161 ]
162 });
163</code></pre>
164<script>goCode("simple", 450, 200)</script>
165<p>
166Note that the <a>Panel.itemArray</a> property is almost always bound to some data property that always has an Array as its value.
167One does not use a literal or constructed Array as the initial value for the Panel.itemArray property in a template,
168unless you expect all parts copied from the template will always have exactly the same unchanging list of items.
169</p>
170<p>
171As with most data bindings, the name of the data property does not really matter.
172In this example, the property name is "items", but you can use whatever name seems appropriate to your app.
173You can also have more than one item array in a node or link.
174</p>
175
176<h2 id="ItemTemplates">Item templates</h2>
177<p>
178You can customize the elements created for each array item by specifying the <a>Panel.itemTemplate</a>.
179The template must be an instance of <a>Panel</a>.
180Each item in the bound Array will get a copy of this Panel that is added to the Panel with the <a>Panel.itemArray</a>.
181The <a>Panel.data</a> will be the item in the Array, so all of the normal data binding functionality is available to customize each item Panel.
182</p>
183<p>
184This use of templates and data binding is similar to the way <a>Node</a>s are created automatically in a <a>Diagram</a> based on an Array of node data in the model.
185The value of <a>Diagram.nodeTemplate</a> must always be a <a>Node</a> or a simple <a>Part</a>;
186the value of <a>Panel.itemTemplate</a> must always be a <a>Panel</a> and cannot be a <a>Part</a>.
187</p>
188<p>
189Note that each item in the <a>Panel.itemArray</a> can be any JavaScript value, including strings and numbers.
190This is different than the values held by the <a>Model.nodeDataArray</a>, which must all be JavaScript Objects.
191The item <a>Panel.data</a> value may be a string, as it is in this example;
192the <a>Part.data</a> value will always be an Object.
193</p>
194<p>
195Here is a simple customization of the <a>Panel.itemTemplate</a>, working with the same model as above.
196Note that the second argument to the <a>Binding</a> constructor in this case is the empty string,
197because strings (and numbers) do not have many useful properties.
198</p>
199<pre class="lang-js" id="vertical"><code>
200 diagram.nodeTemplate =
201 $(go.Node, "Auto",
202 $(go.Shape, "RoundedRectangle",
203 { fill: "#3AA7A3" }),
204 $(go.Panel, "Vertical",
205 new go.Binding("itemArray", "items"),
206 {
207 itemTemplate:
208 $(go.Panel, "Auto",
209 { margin: 2 },
210 $(go.Shape, "RoundedRectangle",
211 { fill: "#91E3E0" }),
212 $(go.TextBlock, new go.Binding("text", ""),
213 { margin: 2 })
214 ) // end of itemTemplate
215 })
216 );
217
218 diagram.model =
219 $(go.GraphLinksModel,
220 {
221 nodeDataArray: [
222 { key: 1, items: [ "Alpha", "Beta", "Gamma", "Delta" ] },
223 { key: 2, items: [ "first", "second", "third" ] }
224 ],
225 linkDataArray: [
226 { from: 1, to: 2 }
227 ]
228 }
229 );
230
231</code></pre>
232<script>goCode("vertical", 450, 200)</script>
233<p>
234However even when binding to strings or numbers one could make the use of converters to get the desired binding values.
235</p>
236
237<p>
238Of course if the array items are Objects, you can refer to their properties just as you can in a <a>Diagram.nodeTemplate</a>.
239As with node data, you can have as many properties on your item data as your app demands, using whatever property names you prefer.
240Use data binding to automatically use those property values to customize the appearance and behavior of your item Panels.
241</p>
242<pre class="lang-js" id="verticalobjects"><code>
243 diagram.nodeTemplate =
244 $(go.Node, "Auto",
245 $(go.Shape, "RoundedRectangle",
246 { fill: "#3AA7A3" }),
247 $(go.Panel, "Vertical",
248 new go.Binding("itemArray", "items"),
249 {
250 itemTemplate:
251 $(go.Panel, "Auto",
252 { margin: 2 },
253 $(go.Shape, "RoundedRectangle",
254 { fill: "#91E3E0" },
255 new go.Binding("fill", "c")),
256 $(go.TextBlock, new go.Binding("text", "t"),
257 { margin: 2 })
258 )
259 })
260 );
261
262 diagram.model =
263 $(go.GraphLinksModel,
264 {
265 nodeDataArray: [
266 {
267 key: 1,
268 items: [
269 { t: "Alpha", c: "orange" },
270 { t: "Beta" },
271 { t: "Gamma", c: "green" },
272 { t: "Delta", c: "yellow" }
273 ]
274 },
275 {
276 key: 2,
277 items: [
278 { t: "first", c: "red" },
279 { t: "second", c: "cyan" },
280 { t: "third" }
281 ]
282 }
283 ],
284 linkDataArray: [
285 { from: 1, to: 2 }
286 ]
287 }
288 );
289
290</code></pre>
291<script>goCode("verticalobjects", 450, 200)</script>
292
293<h2 id="DifferentPanelTypes">Different Panel types</h2>
294<p>
295Although <a>Panel</a>s that have an item array are often of type <a>Panel,Vertical</a>,
296you can use other panel types that support a variable number of elements.
297The most common types are <a>Panel,Vertical</a>, <a>Panel,Horizontal</a>, <a>Panel,Table</a>, and <a>Panel,Position</a>.
298It does not make sense to use a <a>Panel,Viewbox</a> panel, because that panel type only supports a single element.
299</p>
300<p>
301If the panel type is <a>Panel,Spot</a>, <a>Panel,Auto</a>, or <a>Panel,Link</a>,
302the first child element of the Panel is assumed to be the "main" object and is kept as the first child
303in addition to all of the nested panels created for the values in the <a>Panel.itemArray</a>.
304</p>
305<p>
306Here is an example of a horizontal Panel:
307</p>
308<pre class="lang-js" id="horizontal"><code>
309 diagram.nodeTemplate =
310 $(go.Node, "Auto",
311 $(go.Shape, "RoundedRectangle",
312 { fill: "gold" }),
313 $(go.Panel, "Horizontal",
314 { margin: 4 },
315 new go.Binding("itemArray", "a"),
316 {
317 itemTemplate:
318 $(go.Panel, "Auto",
319 { margin: 2 },
320 $(go.Shape, "RoundedRectangle",
321 { fill: "white" }),
322 $(go.TextBlock, new go.Binding("text", ""),
323 { margin: 2 })
324 ) // end of itemTemplate
325 })
326 );
327
328 diagram.model =
329 $(go.GraphLinksModel,
330 {
331 nodeDataArray: [
332 { key: "n1", a: [ 23, 17, 45, 21 ] },
333 { key: "n2", a: [ 1, 2, 3, 4, 5 ] }
334 ],
335 linkDataArray: [
336 { from: "n1", to: "n2" }
337 ]
338 }
339 );
340
341</code></pre>
342<script>goCode("horizontal", 450, 200)</script>
343
344<p>
345When using a <a>Panel</a> of type <a>Panel,Table</a> as the container, it is commonplace
346to use an item template that is of type <a>Panel,TableRow</a> or <a>Panel,TableColumn</a>.
347This is the only way to specify the individual column or row indexes for the elements inside the template.
348</p>
349<pre class="lang-js" id="table"><code>
350 diagram.nodeTemplate =
351 $(go.Node, "Auto",
352 $(go.Shape, { fill: "lightgray" }),
353 $(go.Panel, "Table",
354 new go.Binding("itemArray", "people"),
355 { margin: 4,
356 defaultAlignment: go.Spot.Left,
357 itemTemplate:
358 $(go.Panel, "TableRow",
359 new go.Binding("background", "back"),
360 $(go.TextBlock, new go.Binding("text", "name"),
361 { column: 0, margin: 2, font: "bold 10pt sans-serif" }),
362 $(go.TextBlock, new go.Binding("text", "phone"),
363 { column: 1, margin: 2 }),
364 $(go.TextBlock, new go.Binding("text", "loc"),
365 { column: 2, margin: 2 })
366 ) // end of itemTemplate
367 })
368 );
369
370 diagram.model =
371 $(go.GraphLinksModel,
372 {
373 nodeDataArray: [
374 { key: "group1",
375 people: [
376 { name: "Alice", phone: "2345", loc: "C4-E18" },
377 { name: "Bob", phone: "9876", loc: "E1-B34", back: "red" },
378 { name: "Carol", phone: "1111", loc: "C4-E23" },
379 { name: "Ted", phone: "2222", loc: "C4-E197" }
380 ] },
381 { key: "group2",
382 people: [
383 { name: "Robert", phone: "5656", loc: "B1-A27" },
384 { name: "Natalie", phone: "5698", loc: "B1-B6" }
385 ] }
386 ],
387 linkDataArray: [
388 { from: "group1", to: "group2" }
389 ]
390 }
391 );
392
393</code></pre>
394<script>goCode("table", 450, 200)</script>
395<p>
396Note in this case the item template has a data binding of the TableRow Panel's <a>Panel.background</a> property
397to the item data's "back" property.
398</p>
399
400<p>
401Sometimes one wants to get the row for a particular item, or one wants to have a property value depend on the row index.
402You can always depend on the value of <a>Panel.itemIndex</a> to get that property.
403If the item Panel is of type <a>Panel,TableRow</a>, the item Panel's <a>GraphObject.row</a> property will also be set to the zero-based row number,
404so you can access it in code by finding that Panel.
405The same is true for <a>GraphObject.column</a> if the itemTemplate is a <a>Panel,TableColumn</a> Panel.
406</p>
407<p>
408Because that property is set when the item panels are created for Array item data, you can create <a>Binding</a>s where the source
409is that "row" property: <code>new go.Binding("targetProperty", "row", function(i) { return ...; }).ofObject()</code>.
410The following example demonstrates binding the Panel.background property to be light green if the row is even.
411</p>
412<pre class="lang-js" id="alternating"><code>
413 diagram.nodeTemplate =
414 $(go.Node, "Auto",
415 $(go.Shape, { fill: "white" }),
416 $(go.Panel, "Table",
417 new go.Binding("itemArray", "people"),
418 {
419 defaultAlignment: go.Spot.Left,
420 itemTemplate:
421 $(go.Panel, "TableRow",
422 new go.Binding("background", "row",
423 function(i) { return i%2 === 0 ? "lightgreen" : "transparent" })
424 .ofObject(),
425 $(go.TextBlock, new go.Binding("text", "name"),
426 { column: 0, margin: 2, font: "bold 10pt sans-serif" }),
427 $(go.TextBlock, new go.Binding("text", "phone"),
428 { column: 1, margin: 2 }),
429 $(go.TextBlock, new go.Binding("text", "loc"),
430 { column: 2, margin: 2 }),
431 $("Button",
432 {
433 column: 3,
434 margin: new go.Margin(0, 1, 0, 0),
435 click: function(e, obj) {
436 // OBJ is this Button Panel;
437 // find the TableRow Panel containing it
438 var itempanel = obj.panel;
439 alert("Clicked on row " + itempanel.row + " for " + itempanel.data.name);
440 }
441 },
442 $(go.Shape, "FivePointedStar",
443 { desiredSize: new go.Size(8, 8) })
444 )
445 ) // end of itemTemplate
446 })
447 );
448
449 diagram.model =
450 $(go.GraphLinksModel,
451 {
452 nodeDataArray: [
453 { key: "group1",
454 people: [
455 { name: "Alice", phone: "2345", loc: "C4-E18" },
456 { name: "Bob", phone: "9876", loc: "E1-B34" },
457 { name: "Carol", phone: "1111", loc: "C4-E23" },
458 { name: "Ted", phone: "2222", loc: "C4-E197" },
459 { name: "Robert", phone: "5656", loc: "B1-A27" },
460 { name: "Natalie", phone: "5698", loc: "B1-B6" }
461 ] }
462 ]
463 }
464 );
465
466</code></pre>
467<script>goCode("alternating", 450, 200)</script>
468<p>
469The "Button" Panel in the item template also demonstrates how one can get the particular row index
470as well as the data to which the item panel is bound.
471</p>
472
473<p>
474The natural way to have a distinct header for a Table Panel is to have the first row (i.e. the first item)
475hold the data for the header, but have it be styled differently.
476If you want such a behavior, you will want to use multiple templates -- see the example in <a href="templateMaps.html">Template Maps</a>.
477</p>
478<p>
479If instead you want to have a table header that is "fixed" and not dependent on item Array data,
480you can have a single "TableRow" (or "TableColumn") Panel in the "Table" Panel that is kept if <a>Panel.isPanelMain</a> is true.
481</p>
482<pre class="lang-js" id="header"><code>
483 diagram.nodeTemplate =
484 $(go.Node, "Auto",
485 $(go.Shape, { fill: "white" }),
486 $(go.Panel, "Table",
487 new go.Binding("itemArray", "people"),
488 {
489 defaultAlignment: go.Spot.Left,
490 defaultColumnSeparatorStroke: "black",
491 itemTemplate: // the row created for each item in the itemArray
492 $(go.Panel, "TableRow",
493 $(go.TextBlock, new go.Binding("text", "name"),
494 { column: 0, margin: 2, font: "bold 10pt sans-serif" }),
495 $(go.TextBlock, new go.Binding("text", "phone"),
496 { column: 1, margin: 2 }),
497 $(go.TextBlock, new go.Binding("text", "loc"),
498 { column: 2, margin: 2 })
499 )
500 },
501 // define the header as a literal row in the table,
502 // not bound to any item, but bound to Node data
503 $(go.Panel, "TableRow",
504 { isPanelMain: true }, // needed to keep this element when itemArray gets an Array
505 $(go.TextBlock, "Person",
506 { column: 0, margin: new go.Margin(2, 2, 0, 2), font: "bold 10pt sans-serif" }),
507 $(go.TextBlock, "Phone",
508 { column: 1, margin: new go.Margin(2, 2, 0, 2), font: "bold 10pt sans-serif" }),
509 $(go.TextBlock, "Location",
510 { column: 2, margin: new go.Margin(2, 2, 0, 2), font: "bold 10pt sans-serif" })
511 ),
512 $(go.RowColumnDefinition,
513 { row: 0, background: "lightgray" }),
514 $(go.RowColumnDefinition,
515 { row: 1, separatorStroke: "black" })
516 )
517 );
518
519 diagram.model =
520 $(go.GraphLinksModel,
521 {
522 nodeDataArray: [
523 { key: "group1",
524 people: [
525 { name: "Alice", phone: "2345", loc: "C4-E18" },
526 { name: "Bob", phone: "9876", loc: "E1-B34" },
527 { name: "Carol", phone: "1111", loc: "C4-E23" },
528 { name: "Ted", phone: "2222", loc: "C4-E197" },
529 { name: "Robert", phone: "5656", loc: "B1-A27" },
530 { name: "Natalie", phone: "5698", loc: "B1-B6" }
531 ] }
532 ]
533 }
534 );
535
536</code></pre>
537<script>goCode("header", 450, 200)</script>
538<p>
539In such cases the constant header element, the literal "TableRow" Panel in the node template,
540will have a <a>GraphObject.row</a> == 0 and a <a>Panel.itemIndex</a> that is NaN.
541The "TableRow" Panel corresponding to the first item data, <code>panel.itemArray[0]</code>,
542will have a <a>GraphObject.row</a> == 1, matching its position in the list of <a>Panel.elements</a>.
543But it will have a <a>Panel.itemIndex</a> == 0, matching its position in the itemArray.
544</p>
545
546<h2 id="ArraysInModels">Arrays in Models</h2>
547<p>
548When a data-bound Part is copied, the Part's <a>Part.data</a>, which must be a JavaScript Object, is copied too.
549The normal copying method, <a>Model.copyNodeData</a>, makes a shallow copy of the original data object.
550</p>
551<p>
552However that is probably not the desired behavior for Arrays.
553When you use item Arrays, you normally do <em>not</em> want to share those Arrays between copies of the Node.
554If your node data is not copied correctly, unexpected behavior may occur.
555So when you are using item Arrays and permit users to copy nodes, you will need to make sure such Arrays and their objects are copied.
556For the simplest cases, it may be sufficient to set <a>Model.copiesArrays</a> and <a>Model.copiesArrayObjects</a> to true.
557More generally you may want to implement your own node data copier function
558and assign it to <a>Model.copyNodeDataFunction</a>.
559</p>
560<p>
561This is demonstrated by the <a href="../samples/dynamicPorts.html">Dynamic Ports</a> sample,
562which not only needs to copy the four item Arrays that each node data holds,
563but also each Object that is in each of those Arrays.
564In that sample the <a>Model.copiesArrays</a> and <a>Model.copiesArrayObjects</a> properties
565are set to true in the JSON-formatted representation of the model that is loaded into the diagram.
566</p>
567<p>
568For <a>GraphLinksModel</a>s, there is also a similar members for link data:
569the <a>GraphLinksModel.copyLinkData</a> method and <a>GraphLinksModel.copyLinkDataFunction</a> property.
570</p>
571<p>
572If you need to dynamically modify the value of a property of an item data, call <a>Model.setDataProperty</a>,
573just as you would for node data or link data.
574</p>
575<p>
576If you need to add or remove items from an item Array, call the <a>Model.insertArrayItem</a> or <a>Model.removeArrayItem</a> methods.
577</p>
578
579 </div>
580 </div>
581
582 <div class="bg-nwoods-primary">
583 <section class="max-w-screen-lg text-white container mx-auto py-2 px-12">
584 <p id="version" class="leading-none mb-2 my-4">GoJS</p>
585 </section>
586 </div><footer class="bg-nwoods-primary text-white">
587 <div class="container max-w-screen-lg mx-auto px-8">
588 <div class="w-full py-6">
589
590 <div class="max-w-screen-lg xl:max-w-screen-xl mx-auto px-4 sm:px-6 md:px-8">
591 <ul class="text-sm font-medium pb-14 sm:pb-20 grid grid-cols-1 sm:grid-cols-3 gap-y-10">
592 <li class="list-none row-span-2">
593 <h2 class="text-base font-semibold tracking-wide">GoJS</h2>
594 <ul class="list-none space-y-4 md:space-y-1 px-0">
595 <li>
596 <a href="../samples/index.html">Samples</a>
597 </li>
598 <li>
599 <a href="../learn/index.html">Learn</a>
600 </li>
601 <li>
602 <a href="../intro/index.html">Intro</a>
603 </li>
604 <li>
605 <a href="../api/index.html">API</a>
606 </li>
607 <li>
608 <a href="../changelog.html">Changelog</a>
609 </li>
610 <li>
611 <a href="https://github.com/NorthwoodsSoftware/GoJS">GitHub</a>
612 </li>
613 </ul>
614 </li>
615 <li class="list-none row-span-2">
616 <h2 class="text-base font-semibold tracking-wide">Support</h2>
617 <ul class="list-none space-y-4 md:space-y-1 px-0">
618 <li>
619 <a href="https://www.nwoods.com/contact.html"
620 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/contact.html', 'contact');">Contact</a>
621 </li>
622 <li>
623 <a href="https://forum.nwoods.com/c/gojs">Forum</a>
624 </li>
625 <li>
626 <a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a>
627 </li>
628 <li>
629 <a href="https://www.nwoods.com/sales/index.html"
630 target="_blank" rel="noopener" onclick="getOutboundLink('https://www.nwoods.com/sales/index.html', 'buy');">Buy</a>
631 </li>
632 <li>
633 <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">Videos</a>
634 </li>
635 </ul>
636 </li>
637 <li class="list-none row-span-2">
638 <h2 class="text-base font-semibold tracking-wide">Company</h2>
639 <ul class="list-none space-y-4 md:space-y-1 px-0">
640 <li>
641 <a href="https://www.nwoods.com">Northwoods</a>
642 </li>
643 <li>
644 <a href="https://www.nwoods.com/about.html">About Us</a>
645 </li>
646 <li>
647 <a href="https://www.nwoods.com/contact.html">Contact Us</a>
648 </li>
649 <li>
650 <a href="https://twitter.com/northwoodsgo">Twitter</a>
651 </li>
652
653 </ul>
654 </li>
655 </ul>
656
657
658 <p class="text-sm text-gray-100 md:mb-6">
659 Copyright 1998-2021 <a class="text-white" href="https://www.nwoods.com">Northwoods Software</a>
660 </p>
661 </div>
662 </div>
663</footer> </body>
664
665<script async src="https://www.googletagmanager.com/gtag/js?id=UA-1506307-5"></script>
666<script>
667 window.dataLayer = window.dataLayer || [];
668 function gtag(){dataLayer.push(arguments);}
669 gtag('js', new Date()); gtag('config', 'UA-1506307-5');
670 var getOutboundLink = function(url, label) {
671 gtag('event', 'click', {
672 'event_category': 'outbound',
673 'event_label': label,
674 'transport_type': 'beacon'
675 });
676 }
677
678 // topnav
679 var topButton = document.getElementById("topnavButton");
680 var topnavList = document.getElementById("topnavList");
681 topButton.addEventListener("click", function() {
682 this.classList.toggle("active");
683 topnavList.classList.toggle("hidden");
684 document.getElementById("topnavOpen").classList.toggle("hidden");
685 document.getElementById("topnavClosed").classList.toggle("hidden");
686 });
687</script>
688 <script src="../assets/js/prism.js"></script>
689 <script src="../release/go.js"></script>
690<script src="../extensions/Figures.js"></script> <script src="../assets/js/goDoc.js"></script>
691 <script>
692 document.addEventListener("DOMContentLoaded", function() {
693 if (window.go) document.getElementById('version').textContent = "GoJS version " + go.version;
694 if (window.goDoc) window.goDoc();
695 var d = window.diagrams;
696 for (var i = 0; i < d.length; i++) {
697 var dargs = d[i];
698 goCodeExecute(dargs[0], dargs[1], dargs[2], dargs[3], dargs[4]);
699 }
700 if (window.extra) window.extra();
701 });
702 </script>
703</html>