Update: My working solution based on Bryan’s suggestion:
soc_check_callback=CustomJS(args=dict(full_filter=full_filter, full_list=full_list, datatable=merged_data_table, full_view=full_view, orig_source=true_source, source=merged_source,filt_P90=filt_P90, filt_G90T=filt_G90T , filt_SD855=filt_SD855, filt_E9820=filt_E9820, filt_A13=filt_A13), code='''
full_filter.indices = [];
var labels_length = cb_obj.labels.length;
for(i = 0; i < labels_length; i++) {
if (cb_obj.active.includes(i)) {
//alert("Active! ".concat(i, " ", cb_obj.labels[i])," indices: ", full_filter.indices);
switch(cb_obj.labels[i]) {
case "A13":
//alert("A13 ".concat(empty_filter.indices.length));
for (j=0; j < filt_A13.indices.length; j++) {
full_filter.indices.push(filt_A13.indices[j]);
}
//alert("Post A13 Add ".concat(full_filter.indices));
break;
case "E9820":
//alert("E9820")
for (j=0; j < filt_E9820.indices.length; j++) {
full_filter.indices.push(filt_E9820.indices[j]);
}
break;
case "G90T":
for (j=0; j < filt_G90T.indices.length; j++) {
full_filter.indices.push(filt_G90T.indices[j]);
}
break;
case "P90":
for (j=0; j < filt_P90.indices.length; j++) {
full_filter.indices.push(filt_P90.indices[j]);
}
break;
case "SD855":
for (j=0; j < filt_SD855.indices.length; j++) {
full_filter.indices.push(filt_SD855.indices[j]);
}
}
}
}
full_filter.indices.sort();
source.change.emit()
source.selected.indices = full_filter.indices;
''')
I am learning Bokeh 1.3.4 while creating standalone dashboard charts with interactivity.
My latest challenge is to show a datatable where the user can use checkboxes to limit what columns and rows are shown.
I have solved the column issue by carefully aligning my checkboxgroup indices with my table, and using CustomJS. I include this in case it is of use to a future reader.
columns_check_callback=CustomJS(args=dict(datatable=merged_data_table, orig_columns=backup_merged_columns), code='''
var new_columns = orig_columns.slice()
lab_len=cb_obj.labels.length;
for (i=0;i<lab_len;i++) {
if (cb_obj.active.includes(i) === false) {
new_columns.splice(i,1)
}
}
datatable.columns = new_columns
datatable.change.emit()
''')
Solving the rows issue seems very difficult. I have tried using filters. Right off the bat, if I use multiple IndexFilter or GroupFilters my datatable will show no data. If I have only one filter, then the datatable shows the data.
full_view = CDSView(source=merged_source, filters=[gfilt_A, gfilt_B])
I wonder why is the field called “filters” if it can only function with one.
Ok, I then try changing the indices and updating, but it gets weird. Only the first update “takes”, and subsequent changes are not propagated. ie. The first time I uncheck a box, the correct rows are removed from the display, but the second time the displayed data remains unchanged.
`
new_filter.indices.sort();
new_filter.change.emit()
full_view.filters = [new_filter];
full_view.change.emit();
datatable.change.emit();
`
Right now I am trying to figure out how, in CustomJS, to walk down the rows of the original full datasource and only copy over the rows I currently want ( based on some cell values ) to the source used for display. The tables I am using are small, so even if I have to repeat the walk for each checked box on each callback, I think I will be ok on response time. If someone could help with a simple example showing proper syntax, I would be very grateful!