☰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

Change when PointDrawTool syncs

Community Supportbokehjs
mcginger
mcginger

I’m trying to get custom js code to run during move events for PointDrawTool.

The PointDrawTool docs has a note that mentions:

The data source updates will trigger data change events continuously throughout the edit operations on the BokehJS side. In Bokeh server apps, the data source will only be synced once, when the edit operation finishes.

From a Bokeh server app is it possible to enable continuous syncing?

⌁   Link to post
mcginger
mcginger

@Bryan thanks for the response. Here is an example app:

# file is main.py within a "simple-pointdraw" directory.
from bokeh.models import ColumnDataSource, PointDrawTool, CustomJS
from bokeh.plotting import figure
from bokeh.io import curdoc
from bokeh.layouts import row, layout

left = figure(x_range=(0, 10), y_range=(0, 10), tools=[],
           title='Point Draw Tool')
left.background_fill_color = 'lightgrey'
right = figure(x_range=(0, 10), y_range=(0, 10), tools=[],
           title='Synced Plot')
right.background_fill_color = 'lightgrey'

source = ColumnDataSource({
    'x': [1, 5, 9],
    'y': [1, 5, 9],
    'y2': [2, 6, 10],
    'color': ['red', 'green', 'yellow'],
})

js = """
for (var i = 0; i<cb_obj.data['y'].length; i++) {
	var y = cb_obj.data['y'][i];
	cb_obj.data['y2'][i] = y + 1;
}
cb_obj.change.emit();
"""
source.js_on_change('data', CustomJS(code=js))

left_renderer = left.scatter(x='x', y='y', source=source, color='color', size=10)
right_renderer = right.scatter(x='x', y='y2', source=source, color='color', size=10)

draw_tool = PointDrawTool(renderers=[left_renderer], empty_value='black')

left.add_tools(draw_tool)
left.toolbar.active_tap = draw_tool

curdoc().add_root(row(left, right))
curdoc().title = "Synced Plots"

Run using bokeh serve:

bokeh serve simple-pointdraw

The right plot gets updated y positions only after the point movement is complete. Is there a change.emit() I need to set to see changes during point movement?

⌁   Link to post
Bryan
Bryan

change.emit is purely a JS-side notification, to sync a property back to Python, and actual assignment to the property must be made (i.e. with an “=”)

obj.prop = new_value

I should probably also clarify I was suggesting passing the data on a property of some other model, not the same data source itself. In the past a dummy invisible glyph might have been used for this. In recent versions, a custom DataModel is a better option.

I can easily imagine that updating the same data source as the tool might interfere with the tool. Maybe you will get lucky and it will “work”, but I definitely would not presume that that would be the case.

⌁   Link to post
mcginger
mcginger

I might be misunderstanding you, I’m also a javascript noob :sweat_smile:. I edited my custom js code to:

var tmp_obj = {};
Object.assign(tmp_obj, cb_obj.data)
for (var i = 0; i<cb_obj.data['y'].length; i++) {
	var y = cb_obj.data['y'][i];
	tmp_obj['y2'][i] = y + 1;
}
cb_obj.data = tmp_obj;

but still have the same issue. I’m not quite sure how I would make DataModel work for me in this case. Is there an example you can point me to?

⌁   Link to post
Bryan
Bryan

The callback is never getting called. I had to go look at the source code, but the tool does not result in any observable events being triggered mid-interaction. The CDS changes and events that trigger re-draws are all internal. I don’t think this approach is workable.

Is the “y+1” actually indicative of your real need? If so, then a different approach coudl be a CustomJSTransform for that transforms the to "y" column to provide computed values for the second glyph.

⌁   Link to post
mcginger
mcginger

The actual operation/js-code is more complicated than the example I gave. I took a look at CustomJSTransform and don’t think it quite does what I need. But thanks for the reference, I was unaware of that model, it will come in handy elsewhere.

Is there anyway to set callbacks during that mid-interaction, while moving a point?

⌁   Link to post
Bryan
Bryan

I think the only current way would be to create your own custom extension version of the edit tool. You can also submit a github issue for a feature request, perhaps the current behavior can be made configurable. I don’t have any immediate-term simple suggestions, however.

⌁   Link to post
Bryan
Bryan

Right, I probably should have prefaced by saying that custom extensions are not trivial to begin with, and on even on that scale, a custom edit tool is probably at the extreme end. I think it’s probably feasible to make the sync behavior configurable, though I can’t speculate on exact time frames for the issue to be addressed.

⌁   Link to post

End of archived discussion · Replies are disabled