☰Read-only archive⌕
Looking for help with Bokeh?

This is a read-only archive. Ask questions and join the conversation on GitHub.

Visit Community Support on GitHub →
Archived discussions · Captured October 28, 2026

Conditional logic inside callback not working

Community Supportbokeh
RickD
RickD

The following code works as expected. But in my second code block I apply some if else logic and the code does not work.

from bokeh.models import ColumnDataSource, Div, CustomJS
from bokeh.plotting import column, figure, show
from bokeh.models import PointDrawTool

# prepare some data for base line plot
a1 = [1, 2, 3, 4, 5]
b1 = [6, 7, 2, 4, 5]

p = figure(tools="tap")
p.line(a1, b1, line_width=2) #plot base data

   #next 5 lines will superimpose an interactive scatter plot over base data
   #tap anywhere on plot and new point appears, tap point and press backspace to remove point
   #tap point then left mouse down and drag point to move, then click on point to get coords
source = ColumnDataSource({'x': [1, 5], 'y': [1, 5], 'color': ['red', 'green']})
renderer = p.scatter(x='x', y='y', source=source, color='color', size=20)
draw_tool = PointDrawTool(renderers=[renderer], empty_value='black')
p.add_tools(draw_tool)
p.toolbar.active_tap = draw_tool


div = Div() #create a div below the graph
     #upon tap new point appears then tap again and below code returns x and y coordinates of position tapped
     #when moving point and tapping again new coordinates appear in div below graph
callback = CustomJS(args=dict(source=source, div=div), code="""
    var selectedIndex = source.selected.indices;
    for (var i = 0; i < selectedIndex.length; i++) {
        div.text = `x =  ${source.data['x'][selectedIndex[i]]}`+` and y =  ${source.data['y'][selectedIndex[i]]}`
        }
    """) 

source.selected.js_on_change('indices', callback) #when change event occurs (a tap), run callback

show(column(p,div))

#todo list, need to capture coords of point1 and coords of point2 separately  in order to do some math

Here is my second block, please help me do the conditional logic, thanks

from bokeh.models import ColumnDataSource, Div, CustomJS
from bokeh.plotting import column, figure, show
from bokeh.models import PointDrawTool
import math

# prepare some data for base line plot
a1 = [1, 2, 3, 4, 5]
b1 = [6, 7, 2, 4, 5]

p = figure(tools="tap")
p.line(a1, b1, line_width=2) #plot base data

   #next 5 lines will superimpose an interactive scatter plot over base data
   #tap anywhere on plot and new point appears, tap point and press backspace to remove point
   #tap point then left mouse down and drag point to move, then click on point to get coords
source = ColumnDataSource({'x': [1, 5], 'y': [1, 5], 'color': ['red', 'green']})
renderer = p.scatter(x='x', y='y', source=source, color='color', size=20)
draw_tool = PointDrawTool(renderers=[renderer], empty_value='black')
p.add_tools(draw_tool)
p.toolbar.active_tap = draw_tool


div = Div() #create a div below the graph
     #upon tap new point appears then tap again and below code returns x and y coordinates of position tapped
     #when moving point and tapping again new coordinates appear in div below graph
callback = CustomJS(args=dict(source=source, div=div), code="""
    var selectedIndex = source.selected.indices;
    for (var i = 0; i < selectedIndex.length; i++) {
        div.text = `x =  ${source.data['x'][selectedIndex[i]]}`+` and y =  ${source.data['y'][selectedIndex[i]]}`
        var counter = 1;
        var x1,y1,x2,y2;
        if counter == 1:
            x1 = `${source.data['x'][selectedIndex[i]]}`
            y1 = `${source.data['y'][selectedIndex[i]]}`
            console.log(x1)
            console.log(y1)
            counter=counter+1;
        elif counter == 2:
            console.log(counter)
            x2 = `${source.data['x'][selectedIndex[i]]}`
            y2 = `${source.data['y'][selectedIndex[i]]}`
            counter=1;
        var p1,p2,slope;
        p1 = x2-x1;
        p2 = y2-y1;
        slope = p2/p1;
        }
    """) 

source.selected.js_on_change('indices', callback) #when change event occurs (a tap), run callback

show(column(p,div))
⌁   Link to post
Bryan
Bryan

For one thing, you have written the if...else conditional using Python syntax. What you have above is not valid JavaScript. See e.g. this for more details about how to write conditionals in JavaScript

⌁   Link to post
RickD
RickD

thanks Bryan, I was thinking of this too so here is what i did. But in second pass of for loop my x2 and y2 are undefined.

callback = CustomJS(args=dict(source=source, div=div), code="""
    var selectedIndex = source.selected.indices;
    for (var i = 0; i < 2; i++) {
        div.text = `x =  ${source.data['x'][selectedIndex[i]]}`+` and y =  ${source.data['y'][selectedIndex[i]]}`
        var counter = 1
        var x1=0
        var x2=0
        var y1=0
        var y2=0
        if (i == 0){
            console.log(i)
            x1 = `${source.data['x'][selectedIndex[i]]}`
            y1 = `${source.data['y'][selectedIndex[i]]}`
            console.log(x1)
            console.log(y1)
            }
        else if (i == 1){
            console.log(i)
            console.log("we are in i=2 now")
            x2 = `${source.data['x'][selectedIndex[i]]}`
            y2 = `${source.data['y'][selectedIndex[i]]}`
            console.log(x2)
            console.log(y2)
            }
        }
    """) 
⌁   Link to post

End of archived discussion · Replies are disabled