javascriptangularjscytoscape.jscytoscape-web

Cytoscape event cxttap called multiple times


I am trying to create a network workflow with Cytoscape and AngularJS 1.6 After creating two nodes, user is able to create an edge between them. For this I am using cy.on('cxttap') cytoscape function to detect right clicks on both the nodes and then insert a new edge. This works fine. Until I added a new view, where the user can see saved workflows from the database. The problem is, if I open the Viewing tab and then go back to creation tab, the cy.on('cxttap') function is called twice, and two edges are inserted on the cytoscape canvas, but only one entry is made in my scope variable. I used to have the same factory for both the views but now I am using different angular factories for each.

If I open switch between these tabs multiple times, the number of times I open the viewing tab, is the number of times the function is called, hence more the number of lines.

Here (https://jsfiddle.net/y47kwpg7/4/) is the snippet with the code for both my views with their controllers. "Creation View" --> "MlalTextWorkflowGeneratorCtrl" and "Viewing View" --> "MlalTextWorkflowViewerCtrl".

(Please forgive me, I don't know how to make it work in a single file)

The factory I have here is for the cytoscape canvas, and have a similar one for another view, but with a different id selection.

Thank you for your help!


Solution

  • @maxkfranz 's answer guided me to do a little more debugging and finally I found out the problem.

    The problem was I had some listener functions that I called from my controller in order to detect events on the cytoscape nodes. And the listeners to fire were stored in a a variable workflowGraph.listeners. you can see the old code []1. The problem was this variable was not emptied anytime my controller was reloaded, because I was calling the listeners from my controller, they were being added to this variable once again. So, one listener had multiple functions to call.

    The method I used to solve this was to create a new "listener" type function I had earlier for cytoscape events, which I would call everytime my controller is loaded, to empty the listeners variable for my cytoscape factory.

    In cytoscape factory

        workflowGraph.reinitialize = function () {
            workflowGraph.listeners = {};
        };
    

    In controller

    workflowCreation is the name of the factory

      workflowCreation.reinitialize();
    

    This would simply empty the listeners variable from the factory.

    Remember to call this in your controller after cytoscape initialisation and before calling any other listener functions

    Hope this helps someone.