Tracking the deletion of links

Hi @jhardy Thanks for your reply, I have another question, I have tried to use the tree mapper and I can generate new links but when I remove them and save it tells me that there are no changes, do you know how I can make it take into account when I delete a line, thanks, I await any comments.

The normal operation when the user is editing a diagram is for the code to modify the model data (node data and link data Arrays) to keep it up-to-date with what is showing. The CommandHandler and the various Tools will call Model or GraphLinksModel methods to make those changes to the model data.

So it should be the case that the LinkingTool, which the user is using to draw a new Link from a Node to another Node, will be updating the GraphLinksModel.linkDataArray. At the end of each transaction everything should be consistent between what’s in the model and what’s in the diagram.

Thus it makes sense that newly drawn links will have their corresponding link data objects already present in the GraphLinksModel.linkDataArray. The same is true for the CommandHandler.deleteSelection command – it removes data objects from the model.

Hi @walter
Thanks for your reply, I’ve tried to do what you suggested, but I have two problems with that, the first code “addModelChangedListener” only shows me the last change, and if I delete the links it works unless it’s the last link in the diagram and the second “addModelChangedListener” shows me the changes but not when I delete a link and I want it to know to delete it so that it goes to save the new model in the database, could you guide me, thanks, I await any comment

let previousLinkDataArray = [...(diagram.model as go.GraphLinksModel).linkDataArray];

  diagram.addModelChangedListener((e) => {
    if (e.modelChange === "linkDataArray") {
      const model = e.model as go.GraphLinksModel;
      if (model && Array.isArray(model.linkDataArray)) {
        console.log("model.linkDataArray", model.linkDataArray);

        // Comprobar el estado anterior y actual
        console.log("Previous link data:", previousLinkDataArray);
        console.log("Current link data:", model.linkDataArray);

        mappingLinks = model.linkDataArray
          .filter((link: any) => link.category === 'Mapping')
          .map((link: any) => ({
            origin: link.origin || '',
            from: link.from,
            to: link.to,
            group: link.group || -1,
            package_id: link.package_id || '',
          })) as MappingData[];

        console.log("Model changed - Updated mappingLinks:", mappingLinks.length);
      }
    }
  });

  diagram.addModelChangedListener((e) => {
    if (e.modelChange === "linkDataArray") {
      const model = e.model as go.GraphLinksModel;
      if (model && Array.isArray(model.linkDataArray)) {
        previousLinkDataArray = [...model.linkDataArray];
        console.log("Previous link data:", previousLinkDataArray);
      }
    }
  });
const handleSave = async () => {
  console.log("1-SAVE**************", mappingLinks.length)
  if (mappingLinks.length > 0) {
    try {
      await $treeMapperApi.saveMappingLinks(mappingLinks);
      alert('Mapping saved successfully');
      mappingLinks.splice(0, mappingLinks.length);
    } catch (error) {
      console.error('Error saving mapping links:', error);
      alert('There was an error saving the mapping');
    }
  } else {
    console.log("SAVE**************", mappingLinks.length)
    alert('There are no links to save');
  }
};

I don’t think I suggested that…

For just the case of deleting the selection, you could implement a “SelectionDeleted” DiagramEvent listener. The value of DiagramEvent.subject will be the collection of Parts that were removed.

The more general way to handle changes to models is to implement a “ModelChanged” listener that, when the transaction has finished or an undo or redo has finished, you can examine all of the ChangedEvents in the Transaction and decide which ones you want to pay attention to. This is somewhat explained by this section: Changed Events | GoJS

Also there’s the Update Demo: Update Demo | GoJS
Look at the code in the description of the sample.

Hi @walter, great, thanks for sending me the demo and the code, it will help me a lot to be able to replicate it.

From reading your code in Ordering of links at node - #6 by Maria I think it would be useful if you turned on having the GraphLinksModel maintain a unique key for each link data object in the GraphLinksModel.linkDataArray, just like the key that is always maintained by all Models for each node data object in the Model.nodeDataArray.

You can do that by setting GraphLinksModel.linkKeyProperty to the name of the property on the link data object that you want to hold the key value. Typically you would call it “key” or maybe “id”.

That way you can depend on the “key” for identifying or finding particular links, rather than doing a linear search through all links for one that has the desired “from” node key and the “to” node key. Just call GraphLinksModel.findLinkDataForKey or GraphLinksModel.containsLinkData, depending on whether you have the key or the reference to the link data object.

Then when a link is deleted you just have to save the key, not a bunch of values that hopefully uniquely describe the link. This is also demonstrated by the Model.toIncrementalJson method Model | GoJS API which produces a summary of the effects of a Transaction.