Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

175
Vistas
Panel - JSCallback function - Linking stream data to a JSObject in Echarts within a Panel dashboard

The goal is to stream data into panel and show the current temperature in a Gauge. Panel EChart Gauge

Therefore I am using the callback function for the panel to retrieve a new temperature value and like to update the Gauge as well with the JSCallback function.

Panel JSCallback Function

I also looked into the following questions on stackoverflow:

  • CustomJSCallback
  • Updating existing plot
  • Dynamically updating a Holoviz Panel layout

Here is the current code:

import time
import panel as pn
import random

random.seed()

def read_temp():
    return random.randint(15, 30)

global temperature
temperature = read_temp()

# Stream function
def stream():
    temperature = read_temp()
    print(temperature)
    #how to access the js object?
    pn.state.jscallback(args={'gauge': gauge_pane}, value="""
gauge.data.series[0].data[0].value = """+str(temperature))

gauge = {
    'tooltip': {
        'formatter': '{a} <br/>{b} : {c}°C'
    },
    'series': [
        {
            'name': 'Gauge',
            'type': 'gauge',
            'detail': {'formatter': '{value}°C'},
            'data': [{'value': [temperature], 'name': 'Temperature'}]
        }
    ]
};

#Panel
pn.extension('echarts',sizing_mode="stretch_width",template="fast")
ACCENT = "orange"
pn.state.template.param.update(site="Test", title="Introduction to data apps with Panel", 
                               sidebar_width=200, accent_base_color=ACCENT, 
                               header_background=ACCENT, font="Montserrat")
gauge_pane = pn.pane.ECharts(gauge,width=400, height=400).servable()

pn.pane.JPG("logo.jpg", sizing_mode="scale_width", embed=False).servable(area="sidebar")
pn.panel("# Settings").servable(area="sidebar")

# Set up callback with streaming data
pn.state.add_periodic_callback(stream, 500)

May be someone from the panel developers / community has some hints or some example. I mainly like to understand how I can access the JS Objects to be updated in the panel. So maybe JSLink is the right way to do it? If yes how would that work with my little example? - Thank you! :-)

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

There is no easy way to call a jscallback from python, I think, but I am not sure. Bokeh callbacks with CustomJS: is there a way to trigger a callback with CustomJS from inside another callback with custom JS?

I think your problem is related there is no pn.state.jscallback (or maybe I am not aware of that).

I added a dummy slider, which is not visible, to use the callback attached to this slider. When you change the slider value, the callback is triggered internally by panel. This is good because the js_callback always has a cb_obj object in the javascript code, which you can use to pass the temperature generated with the random.randint function. I think you do not need to define the temperature global in that case either.

A gif of the solution working is here https://discourse.holoviz.org/uploads/default/original/2X/f/f65a8da7b3224b1a6a86b57e4ddd20dc0aa11bb1.gif


import time
import panel as pn
import random

random.seed()

def read_temp():
    return random.randint(15, 30)

global temperature
temperature = read_temp()

slider = pn.widgets.FloatSlider(visible=False)

# Stream function
def stream():
    temperature = read_temp()
    print('in python', temperature)
    #how to access the js object?
    slider.value = random.randint(0, 30) # this step triggers internally the js_callback attached to the slider 

gauge = {
    'tooltip': {
        'formatter': '{a} <br/>{b} : {c}°C'
    },
    'series': [
        {
            'name': 'Gauge',
            'type': 'gauge',
            'detail': {'formatter': '{value}°C'},
            'data': [{'value': [temperature], 'name': 'Temperature'}]
        }
    ]
};

# Set up callback with streaming data
pn.state.add_periodic_callback(stream, 500)

#Panel
pn.extension('echarts',sizing_mode="stretch_width",template="fast")
ACCENT = "orange"
pn.state.template.param.update(site="Test", title="Introduction to data apps with Panel", 
                               sidebar_width=200, accent_base_color=ACCENT, 
                               header_background=ACCENT, font="Montserrat")

gauge_pane = pn.pane.ECharts(gauge,width=400, height=400)

row = pn.Row(gauge_pane,slider).servable()

slider.jscallback(args={'gauge': gauge_pane}, value="""
    console.log( 'dummy slider:', cb_obj.value, 
            'gauge value',gauge.data.series[0].data[0].value);
    gauge.data.series[0].data[0].value = cb_obj.value;
    gauge.properties.data.change.emit()"""
    )



# pn.pane.JPG("logo.jpg", sizing_mode="scale_width", embed=False).servable(area="sidebar")
pn.panel("# Settings").servable(area="sidebar")
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda