Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change label of node within callback using Dash Cytoscape

I have created some nodes with Dash Cytoscapes. My final goal is that there should appear a Slider after clicking on a node. By selecting a value with this Slider the label of the node should be updated with the selected value. Since Im not able to display the slider after clicking a node I made it be displayed permanently below the nodes. Hopefully you got some ideas to reach my desire.

import dash
from dash import dcc
from dash import html
from dash.dependencies import Input, Output
import dash_cytoscape as cyto

app = dash.Dash(__name__)

app.layout = html.Div([
        cyto.Cytoscape(  
        id='node-callback-event',
        layout={'name': 'preset'},
        style={'width': '100%', 'height': '2000px', 'display': 'block'},
        elements=[
            {
                'data': {'id': 'root', 'label': 'test label'},
                'position': {'x': 750, 'y': 750},
                'locked': True
            }
        ]
    ),
        html.Label('Slider'),
        dcc.Slider(
            id='slider-update-value',
            min=0,
            max=100,
            value=0,
            step=0.01,
            tooltip = {"placement": "bottom", 'always_visible': False },
            included=False,
            updatemode='drag',
        ),
    ], 
    style={'padding': 1, 'flex': 1})

@app.callback(Output('node-callback-event', 'elements'),
              Input('node-callback-event', 'tapNodeData'),
              Input('slider-update-value', 'value'))
def displayTapNodeData(node, probability):
    if node:
        node['label'] += str(probability)


# how to assign the value to the nodes label? 

if __name__ == '__main__':
    app.run_server(debug=True)
like image 789
Baflora Avatar asked Sep 17 '25 09:09

Baflora


1 Answers

You can wrap the slider in a div element, which you can hide by default using the hidden property :

html.Div(id='slider', hidden=True, children=[
    html.Label('Slider'),
    dcc.Slider(
        id='slider-update-value',
        # options...
    )
])

Then update that property when a node get selected using tapNodeData or selectedNodeData event, I use selectedNodeData here because the other is not fired when you unselect a node (ie. if you want to hide the slider back) :

@app.callback(
    Output('slider', 'hidden'),
    Input('node-callback-event', 'selectedNodeData'))
def displaySlider(data):
    return False if data else True

Now, given the Input value of the slider, you want to update the Output of the Cytoscape elements, given the State of the currently selected node(s) (tapNodeData or selectedNodeData again) :

@app.callback(Output('node-callback-event', 'elements'),
            Input('slider-update-value', 'value'),
            State('node-callback-event', 'elements'),
            State('node-callback-event', 'selectedNodeData'))
def updateNodeLabel(value, elements, selected):
    if selected:
        # Update only the selected element(s)
        ids = [nodeData['id'] for nodeData in selected]
        nodes = ((i,n) for i,n in enumerate(elements) if n['data']['id'] in ids)
        for i, node in nodes:
            elements[i]['data']['label'] = 'test-' + str(value)
    return elements

@see Cytoscape callbacks and events

like image 142
EricLavault Avatar answered Sep 19 '25 23:09

EricLavault