Difference between Bokeh and Panel Button

Hi !

After a while I am not understanding the difference between the bokeh and the panel button. I think in the panel button the triggering in the JS side is lost.

In my example I am updating a CDS with a multilne ghlyph. It produces the update in python, but not in JS. You can change in the example the type of button

import panel as pn, numpy as np
pn.extension()
from bokeh.models import ColumnDataSource, CustomJS, Button
from bokeh.plotting import figure 

p = figure(title='I', height=450)

lx =[np.arange(i,i+10) for i in [3,20, 40]]
ly =[np.arange(i,i+10) for i in [3,20, 40]]

source = ColumnDataSource(dict(xs=lx, ys=ly) )

p.multi_line(xs='xs',ys='ys', source=source)


# btn = Button(name='update') # working 
btn = pn.widgets.Button(name='update')

def update_cds(event):
    lx =[np.arange(i,i+5) for i in [5,10, 15,20,40]]
    ly =[np.arange(i,i+5) for i in [5,10, 15,20,40]]
    source.data = dict(xs=lx, ys=ly)
    print (' Python: working or not working ??')

source.js_on_change('data', 
            CustomJS(code = "console.log('JS:data_change_detected');"))    
    
btn.on_click(update_cds)

pn.Column(btn,p)

A gif showing my problem

Hi @nghenzi

I believe this is an error 40 :slight_smile:

Every time you click the button you are updating the plot with the same data. Thus you don’t see any change.

Try this.

import panel as pn, numpy as np
pn.extension()
from bokeh.models import ColumnDataSource, CustomJS, Button
from bokeh.plotting import figure

p = figure(title='I', height=450)

lx =[np.arange(i,i+10) for i in [3,20, 40]]
ly =[np.arange(i,i+10) for i in [3,20, 40]]

source = ColumnDataSource(dict(xs=lx, ys=ly) )

p.multi_line(xs='xs',ys='ys', source=source)


# btn = Button(name='update') # working
btn = pn.widgets.Button(name='update')

TOGGLE = True

def update_cds(event):
    global TOGGLE
    if TOGGLE:
        lx =[np.arange(i,i+5) for i in [5,10, 15,20,40]]
        ly =[np.arange(i,i+5) for i in [5,10, 15,20,40]]
    else:
        lx =[np.arange(i,i+10) for i in [3,20, 40]]
        ly =[np.arange(i,i+10) for i in [3,20, 40]]
    source.data = dict(xs=lx, ys=ly)
    TOGGLE=not TOGGLE
    print (' Python: working or not working ??')

source.js_on_change('data',
            CustomJS(code = "console.log('JS:data_change_detected');"))

btn.on_click(update_cds)

pn.Column(btn,p).servable()

Thank you very much @Marc for the fast response !!!. Did you try this code in a jupyter notebook ?

With servable and panel.serve it works as shown in the right side of the gif, but if I show the plot in the notebook as shown in the left side it does not trigger the JS update. Now I am thinking and I am not sure if it should work inside the jupyter notebook without .show or .servable ?

Maybe I have some problem with the environment, but I tried 3 different environments (and update them too). Thank you very much again !!! After checking again, I think I have some problem with the notebook

Excuse me for bothering you. In any case I would like to understand the different behavior between the bokeh and the panel button. With your code in the notebook the same difference between the bokeh and the panel button appears.

As you rightly pointed out this is similar to https://github.com/holoviz/panel/issues/1618 which has now been fixed on master.

1 Like

Thanks for the quick fix !

1 Like