Javascript return value in streamlit component

Got it! You want to create a well-structured discussion post for a forum (like the Streamlit Community forum or Stack Overflow) to get help with your PyVis + Streamlit integration. Here’s a template you can use. I’ve tailored it to your case, including all the necessary details the forum recommends. You just need to fill in a few placeholders:


Title:

PyVis Graph in Streamlit: Highlight Nodes and Send Clicked Node ID to Backend


Body:

Hi everyone,

I’m trying to integrate an interactive PyVis network graph into Streamlit. I want the following behavior:

  1. Clicking a node should highlight connected nodes (incoming/outgoing).

  2. Clicking a node should also send the node ID back to Streamlit .

Right now, my setup highlights nodes correctly, but I cannot retrieve the clicked node ID in Streamlit. I’ve tried components.html, st_javascript, and streamlit_js_eval, but I’m either getting DeltaGenerator objects or 0, and the value never updates.


Environment:

  • Streamlit version: 1.29.0

  • Python version: 3.10.12

  • OS: Linux


Code snippet:

import streamlit as st
import streamlit.components.v1 as components
from streamlit_javascript import st_javascript

# Load PyVis HTML
with open("claims_dependency.html", "r", encoding="utf-8") as f:
    html_content = f.read()

highlight_js = """
function highlightNode(params) {
    nodes.update(nodes.get().map(n => ({id: n.id, color: n.originalColor})));
    if (params.nodes.length === 0) return;

    var selectedNode = params.nodes[0];
    var incoming = network.getConnectedNodes(selectedNode, 'from');
    incoming.forEach(nid => nodes.update({id: nid, color: 'rgba(205,175,140)'}));
    var outgoing = network.getConnectedNodes(selectedNode, 'to');
    outgoing.forEach(nid => nodes.update({id: nid, color: 'rgba(204,255,153)'}));
    
    window.lastClickedNode = selectedNode;
}

nodes.get().forEach(n => n.originalColor = n.color);
network.on("click", highlightNode);
"""

html_content = html_content.replace("</body>", f"<script>{highlight_js}</script></body>")

col1, col2 = st.columns([2,1])

with col1:
    st.subheader("Claims Dependency Graph")
    components.html(html_content, height=900, width=1200)

with col2:
    st.subheader("📄 Claim Metadata")
    clicked_node = st_javascript("window.lastClickedNode")
    
    if clicked_node:
        st.session_state["clicked_node"] = clicked_node

    if "clicked_node" in st.session_state:
        st.write("Clicked node:", st.session_state["clicked_node"])
    else:
        st.info("Click a node in the graph to see metadata")


Issue / Error Messages:

  • clicked_node always returns 0 or a DeltaGenerator object.

  • Using return in JS does not propagate the value to Streamlit.

  • I’ve tried multiple approaches, including streamlit_js_eval and st_javascript, but cannot get the value reliably.

  • Node highlighting works correctly.


What I’ve tried:

  1. Returning the clicked node from JS via return → does not work with components.html.

  2. Using st_javascript("window.lastClickedNode") → returns 0 or DeltaGenerator.

  3. Using streamlit_js_eval → also doesn’t update dynamically.


Question:

How can I capture the clicked node ID in Streamlit while keeping PyVis node highlighting intact?


Additional notes:

  • App is running locally (or deployed)

  • Only need single node ID per click