Visdcc & dcc.dropdown: unable to select node on dropdown selection

Below is a simple dash app that makes use of the wonderful visdcc code written by @jimmybow

It has a dcc.Dropdown component used to search nodes and a visdcc component to display the network graph.

The goal is to

  1. allow the user to click on a node (or select it from the dropdown) and have it centered
  2. when the user clicks elsewhere on the canvas (off of a node), return the view to its original state

Point 1 works.

However, Point 2 only works if the user has previously clicked on a node; it does not work when the user has previously selected a node via dropdown as the update_dropdown callback is (inexplicably to me) not called.

My guess is that when using the dropdown I must also somehow select the node in the graph, perhaps using the selectNodes() method from the vis.js API, but this method is not supported by visdcc.

Any advice on how to overcome this hurdle would be much appreciated :slight_smile:

# -*- coding: utf-8 -*-

import dash
import visdcc
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

app = dash.Dash()

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' },
]

edges = [
    { 'from': 1, 'to': 3 },
    { 'from': 1, 'to': 2 },
    { 'from': 2, 'to': 4 },
    { 'from': 2, 'to': 5 },
    { 'from': 3, 'to': 3 },
]

data = {
    'nodes': nodes,
    'edges': edges
}

app.layout = html.Div([
    dcc.Dropdown(
        id='node-search',
        options=[{'label':node['label'],'value':node['id']} for node in nodes],
        placeholder="Search",
        searchable=True,
        clearable=True,),
    visdcc.Network(
        id = 'net',
        data = data,
        options = dict(height= '600px', width= '100%')),
])


@app.callback(
    Output('node-search', 'value'),
    Input('net', 'selection'))
def update_dropdown(x):
    if not x or len(x['nodes']) == 0:
        return None
    return str(x['nodes'][0])


@app.callback(
    Output('net', 'fit'),
    Input('node-search', 'value'))
def update_graph(node):
    if not node:
        return {'animation':True}
    return {'nodes': [node], 'animation':True}


if __name__ == '__main__':
    app.run_server(debug=True)
1 Like

I have a similar issue. I wanted to use the selectNodes() method but it does not seem to work with visdcc. Have you found a workaround?

You can use the visdcc method run to use selectNodes() method with javascript:

Here below is a simple example where I have 2 instances of the same visdcc.Network called net1 and net2. The goal is to reproduce the selection of net1 in net2. When I select a node in net1, I run selectNodes through javascript on net2 and l assign the selection of net1 to the selection property of net2.

@app.callback(
    Output("net2, "run"),
    Output("net2", "selection"),
    Input("net1", "selection"),
)
def update_net1(selection_net2):
    javascript = f"this.net.selectNodes({selection_net2['nodes']})"
    return selection, javascript