Issue with Link Key Handling in GoJS 3.x After Upgrade from 2.x

Hi @walter,

We recently upgraded from GoJS 2.x to 3.x, and encountered a change in behavior regarding link keys and how they are handled during runtime updates.

Scenario in GoJS 2.x:

  • When a link is drawn between two nodes, an event is triggered where the link data includes a key (auto-decremented negative number).
  • We relied on this key to store and later update link-specific data.
  • Using diagram.findLinkForKey(key) worked with both numeric values (e.g., -10) and their string equivalents ("-10").
  • We were able to update link data seamlessly using the key.

Issue in GoJS 3.x:

  • After the upgrade, we’re unable to update link data in the same way.

  • diagram.findLinkForKey(key) finds the link if we use the numeric key (e.g., -10), but updating the data only works if we convert the key to a string (e.g., "-10").

  • We attempted to explicitly convert the key using:

    diagram.model.commit(model => {
      model.setKeyForLinkData(linkData, linkData.key.toString());
    }, 'Updating the key');
    
  • After this change, diagram.findLinkForKey(uuid) or even the stringified key returns null, though we can still find it with the original auto-generated key. On reload, everything works as expected — the updated keys are recognized and updates persist.

Summary of Problem:

  • In GoJS 3.x, after modifying the link key using setKeyForLinkData, we are unable to find or update the link data during the same runtime session using the new key.
  • Only after a reload (and re-parsing the model) does the updated key behave correctly.

Questions:

  1. Has there been a change in how GoJS 3.x handles link keys internally?
  2. Is there a recommended way to dynamically change and work with link keys at runtime in 3.x?
  3. Why does findLinkForKey() behave differently between numeric and string keys in 3.x?

Any guidance or recommended practices to resolve this would be greatly appreciated.

Thanks in advance!

Yes, as documented in the 3.0 change log: Change Log | GoJS

GoJS Set and Map used to consider both a string and a number of the same value (e.g. “3.14159” and 3.14159) as the same key. They are now considered different keys. Be sure to always get with the same type of value that you added to the Set or set in the Map.

Those auto-generated key values are numbers.

We designed and implemented the go.Set and go.Map classes before the JavaScript Set and Map classes were even proposed for ES2015. Fortunately, they are moderately compatible, except for iteration.

Hi @walter,

We have a question about customizing link keys.

We’d like to assign a custom key to a link instead of using the autogenerated one. Is there a way to pass a custom key generation function when a link is created? Alternatively, can we update the key after the link is drawn?

We tried the second approach — updating the key after the link is drawn — like this:

diagram.model.commit(model => {
  model.setKeyForLinkData(linkData, NEW_UUID_KEY);
}, 'Updating key after link creation');

After doing this, the linksDataArray does reflect the updated key (NEW_UUID_KEY). However, when we call:

diagram.findLinkForKey(NEW_UUID_KEY);

…it returns null. But the original autogenerated key still works when used with findLinkForKey.

It seems like the new key isn’t being recognized in the model instance, even though it appears updated in the data.

Are we missing a step here to fully update the internal model so that findLinkForKey recognizes the new key?

Thanks!

First, here are two quotes from https://gojs.net/latest/api/symbols/GraphLinksModel.html:

However you may wish to have the model maintain string or number identifiers on the link data just as all models do for node data. To get that behavior, so that you can call findLinkDataForKey, you need to set linkKeyProperty to be a non-empty string. Just as with the assignment of node keys, you can customize the assignment of link keys by setting makeUniqueLinkKeyFunction to a function that returns a unique identifier.

Unless linkKeyProperty is set to a non-empty string, this model will not automatically assign unique key values for link data objects, and thus this method (findLinkDataForKey) will always return null.

If the link data should have unique keys, one must first set GraphLinksModel.linkKeyProperty. You can then call GraphLinksModel.findLinkDataForKey and GraphLinksModel.setKeyForLinkData and Diagram.findLinkForKey.

If you want to control the range and format for link keys, set GraphLinksModel.makeUniqueLinkKeyFunction. Again, you will want to set this before adding any link data to the model. Remember to set it again immediately after getting a model from Model.fromJson.