Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing a Nodes Label parameter value in Vis.js

I am trying to access a nodes label parameter value in a vis.js dataset. I know I can get the nodeId from var nodeId = params.nodes[0];

How can I access the value of the Label parameter for Node id=2?

// create an array with nodes
var nodes = [
    {id: 1, label: 'Node 1'},
    {id: 2, label: 'Node 2'},
    {id: 3, label: 'Node 3'},
    {id: 4, label: 'Node 4'},
    {id: 5, label: 'Node 5'}
];

// create an array with edges
var edges = new vis.DataSet([
    {from: 1, to: 3},
    {from: 1, to: 2},
    {from: 2, to: 4},
    {from: 2, to: 5}
]);

// create a network
var container = document.getElementById('mynetwork');
var data = {
    nodes: nodes,
    edges: edges
};


network.on("click", function (params) {

    if (params.nodes.length > 0) {

        var nodeId = params.nodes[0];
like image 775
Barry Cullen Avatar asked Mar 08 '23 16:03

Barry Cullen


1 Answers

If you can really guarantee that you'll follow a convention that node ids are integers in order, starting with 1, then, to answer the question, you could access the label as in the following click callback:

network.on("click", function(params) { // NOT RECOMMENDED 
    if (params.nodes.length > 0) {  
        var nodeId = params.nodes[0];
        console.log("Clicked on a NODE with id = " + nodeId + ", label = " + 
           nodes[nodeId - 1].label);        
    }
});

(Subtracting the 1 was needed because arrays are indexed from 0, but the ids start at 1)

However, that wouldn't be good coding practice, as it is too dependent on always getting the convention right. That convention could break down if you ever start operations like deleting nodes, using strings for ids, etc.

Another approach would be to use internal structure in the network object. The problem is that the user documentation doesn't mention this, so it's somewhat risky -- it could change in future versions. Poking around in the internal structure, I found you could use the following:

console.log("..Or, using undocumented internal structure, node label = " + 
    this.body.nodes[nodeId].options.label);

As far as I know, getting node and edge information from the network object isn't documented for users of vis.js. For using graph algorithms, nodes and edges are key objects of interest, yet those are undocumented hidden internal objects. So, we take some risks that might be considered bad coding practice.

The recommended practice of vis.js, is to make the nodes a vis.DataSet. You had already made the edges a vis.DataSet - why not the nodes as well?

Then, the specification of nodes looks like

var nodes = new vis.DataSet([
    {id: 1, label: 'Node 1'},
    {id: 2, label: 'Node 2'},
    {id: 3, label: 'Node 3'},
    {id: 4, label: 'Node 4'},
    {id: 5, label: 'Node 5'}
]);

and a click callback showing the label would look like

network.on("click", function(params) {
    if (params.nodes.length > 0) {
        var nodeId = params.nodes[0];
        console.log("Clicked on a NODE with id = " + nodeId + ", label = " + 
            nodes.get(nodeId).label);           
    }
});

You will also have access to other DataSet methods such as add() and update(), for example,

nodes.add({id: 6, label: 'Node 6'});
nodes.update({id: 6, label: "Modified node 6", newVar: "A new property"}); 

Using a DataSet and these methods allows you to enter nodes and edges in any order, for any id, including integers and strings. This should all be efficient: Internally, it looks like the key access to nodes and edges is through references to object properties, not array indexing, so that access should be fast. The API's tend to generate arrays for user convenience, but it's generating them, not just copying them.

Having to maintain some node information separately from the network object seems somewhat awkward from a user standpoint, especially if there is more than one network object. But at least this approach uses only the published API.

like image 112
gms Avatar answered Mar 21 '23 03:03

gms