Error in iterating over links and adding new links

i m working on a diagram this is a follow up to my last question which u answered by saying me to add links to diagram instead of model in loading the model now i m trying to iterate over link data to put virtual links in my diagram using this code

function makeVirtualLinks()
{
var checkJson={};
myDiagram.links.each(function(link) {

var fromParse = link.fromNode;
var toParse = link.toNode;
var fromGroup=fromParse.data.group;
var toGroup = toParse.data.group;
var linkFlag = checkDupLink(checkJson,fromGroup,toGroup);

if (!linkFlag)
{
  myDiagram.startTransaction("addVlinks");
  var linkdata = Go(go.Link);
    linkdata.fromNode = myDiagram.findNodeForKey("fromGroup");
    linkdata.toNode =  myDiagram.findNodeForKey("toGroup");
    myDiagram.add(linkdata);
    checkJson.fromGroup=toGroup;

    myDiagram.commitTransaction("addVlinks");

      }

}
);

i m getting an error

can i not add links while the itrator is itrating?
do i need to add the data to a separate array? if so is there a way to add collection of links to diagram?

also can you tell me a way to add link data collection to model like i can do with nodes i cant seem to find a function that add linkdatacollection to model

Yes, it’s unsafe to modify a collection while iterating over it. Or, more precisely, it’s an error to continue iterating over a collection after it has been modified.

The idea is that you are adding and removing instances of Link to/from the Diagram. You are not adding and removing data objects to/from the GraphLinksModel. So using the term “data” when you are talking about a Link is misleading/confusing. Keep the split between the left and right halves of this diagram in mind: GoJS Data Binding -- Northwoods Software.

Here’s some code:

    // Whenever the user expands or collapses a group, this gets called.
    // You might also want to call it after loading a diagram
    // or adding/ removing links or making programmatic changes.
    function showIntergroupLinks(node) {
      var diagram = node.diagram;
      // remember all summary links, will delete unneeded ones later
      var summaries = new go.Map(go.Link, "number");
      diagram.links.filter(isSummaryLink).each(function(l) { summaries.add(l, 0); } );

      // iterate over all links, and see which ones need summarization
      var newsummaries = new go.Set(go.Link);
      diagram.links.each(function(l) {
        if (l.fromNode === null || l.toNode === null) return;
        //if (l.fromNode.isVisible() && l.toNode.isVisible()) return;
        var fromvis = l.fromNode.findVisibleNode();
        var tovis = l.toNode.findVisibleNode();
        if (fromvis === null && tovis === null) return;
        if ((fromvis instanceof go.Group && !fromvis.isSubGraphExpanded) ||
          (tovis instanceof go.Group && !tovis.isSubGraphExpanded)) {
          l.visible = false;

          // now deal with Groups; if FROMVIS or TOVIS is a regular Node, use its containing Group instead
          var fromgrp = (fromvis instanceof go.Group) ? fromvis : fromvis.containingGroup;
          if (fromgrp === null) return;
          var togrp = (tovis instanceof go.Group) ? tovis : tovis.containingGroup;
          if (togrp === null) return;

          // don't have summaries from nested groups to nested groups within a group
          if (fromgrp === togrp) return;

          // see if there is already a summary link between these two groups, in either direction
          var summlink = null;
          var it = summaries.iterator;
          while (it.next()) {
            var link = it.key;
            if ((link.fromNode === fromgrp && link.toNode === togrp) ||
                (link.fromNode === togrp && link.toNode === fromgrp)) {
              summlink = link;
            }
          }
          if (summlink === null) {  // if not, create it, remember to add it to the diagram, and add to SUMMARIES
            summlink = makeSummaryLink(fromgrp, togrp);
            newsummaries.add(summlink);
            summaries.add(summlink, 1);
          } else {  // increment usage in SUMMARIES
            summaries.set(summlink, summaries.get(summlink) + 1);
          }
        } else {
          l.visible = true;
        }
      })

      // now add any new summary links
      newsummaries.each(function(l) { diagram.add(l); });
      // and remove any unused summary links
      summaries.each(function(kvp) { if (kvp.value === 0) diagram.remove(kvp.key); });
    }

    // we'll implement summary links as unmodeled links -- no link data
    function isSummaryLink(l) { return l.data === null; }

    function makeSummaryLink(group1, group2) {
      // add an unmodeled Link to the Diagram -- Link.data will be null
      var summlink =
        $(go.Link,  // this cannot have any Bindings
          $(go.Shape, { stroke: "red", strokeWidth: 2 })
        );
      summlink.fromNode = group1;
      summlink.toNode = group2;
      return summlink;
    }