You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bokeh:如何实现CustomJS按钮全量清除DataTable选中状态?

问题分析与解决

问题原因

当使用CDSView过滤DataTable时,Bokeh的DataTable组件会为每个不同的视图维护独立的选中状态缓存。切换滑块(切换视图)时,DataTable会将当前视图对应的缓存选中状态同步回ColumnDataSource的selected.indices中。

你的清除按钮仅清空了当前视图对应的CDS选中索引,但其他视图的选中缓存依然存在。当切回原视图时,DataTable会把缓存的选中状态重新写入CDS,导致之前的选中状态“复活”。

解决方案

修改清除按钮的CustomJS,不仅清空ColumnDataSource的选中索引,还要主动触发DataTable的状态更新,同时确保所有视图的选中缓存被清空。具体做法是将data_table传入CustomJS,直接操作其选中状态并触发变更事件。

修改后的完整代码

import numpy as np
import pandas as pd
from bokeh.io import show
from bokeh.layouts import column
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, CDSView, CustomJS, CustomJSFilter, Slider, TableColumn, DataTable, SelectEditor, Button


x = np.arange(0, 10, 0.1)
dfs = []
tstep = 1
ts = range(0, 100, tstep)
for t in ts:
    y = x**(t/50.)
    dfs.append(pd.DataFrame({"x": x, "y": y, "t": t}))

df = pd.concat(dfs)
cds = ColumnDataSource(df)

t_slider = Slider(start=ts[0], end=ts[-1], step=tstep, value=0)

# Callback to notify downstream objects of data change
change_callback = CustomJS(args=dict(source=cds), code="""
    source.change.emit();
""")
t_slider.js_on_change('value', change_callback)

# JS filter to select data rows matching t value on slider
js_filter = CustomJSFilter(args=dict(slider=t_slider), code="""
const indices = [];

// iterate through rows of data source and see if each satisfies some constraint
for (let i = 0; i < source.get_length(); i++){
    if (source.data['t'][i] == slider.value){
        indices.push(true);
    } else {
        indices.push(false);
    }
}
return indices;
""")
    
# Use the filter in a view
view = CDSView(filter=js_filter)
                           
# Add table to use for selecting data
columns = [
    TableColumn(field="x", title="x", editor=SelectEditor()),
    TableColumn(field="y", title="y", editor=SelectEditor()),
]
data_table = DataTable(source=cds, columns=columns, selectable="checkbox", width=800, view=view)

p = figure(x_range=(0,10), y_range=(0,100))
p.scatter(x='x', y='y', source=cds, view=view)

# Button to clear selection - 修改后的CustomJS
clear_button = Button(label="Clear selection", button_type="success")
custom_js_button = CustomJS(args=dict(source=cds, table=data_table), code="""
// 清空CDS的选中索引
source.selected.indices = [];
// 清空DataTable的选中状态缓存
table.selected.indices = [];
// 触发变更事件,通知所有关联组件更新
source.change.emit();
table.change.emit();
""")
clear_button.js_on_event("button_click", custom_js_button)

layout = column(p, t_slider, data_table, clear_button)
show(layout)

关键修改点

  1. 将data_table作为参数传入CustomJS
  2. 同时清空source.selected.indices和table.selected.indices
  3. 调用source.change.emit()和table.change.emit()强制触发所有组件的状态更新,确保缓存的选中状态被彻底清除

内容的提问来源于stack exchange,提问作者Ben Farmer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 01:41:01