panel
panel copied to clipboard
Tabulator columns width ("fit_data_fill") not refreshing when editing cells
panel 0.14.0
MRE (extract from a larger code)
import param
import panel as pn
import pandas as pd
from bokeh.models.widgets.tables import SelectEditor
pn.extension("tabulator")
class AnnotationCard(pn.viewable.Viewer, pn.viewable.Layoutable):
title = param.String(default="Annotations")
df_annotations = param.DataFrame()
editors = param.Dict()
initialdir = param.String(default=".")
new_row = param.Dict()
table_widths = param.Dict(default={})
table_show_index = param.Boolean(default=False)
table_height = param.Integer(default=207)
table_layout = param.Selector(
default="fit_data_fill",
objects=["fit_columns", "fit_data", "fit_data_stretch", "fit_data_fill", "fit_data_table"],
)
table_pagination = param.Selector(default="local", objects=[None, "local", "remote"])
table_page_size = param.Integer(default=5)
add = param.Event()
delete = param.Event()
def __init__(self, editors, **params):
df_annotations = pd.DataFrame([], columns=list(editors.keys()))
new_row = params.get(
"new_row",
{
k: 0
if isinstance(v, dict) and v["type"] == "number"
else v.options[0] # type: ignore
if isinstance(v, SelectEditor)
else ""
for k, v in editors.items()
},
)
super().__init__(editors=editors, df_annotations=df_annotations, new_row=new_row, **params)
self._annotations_table = pn.Param(
self,
parameters=["df_annotations"],
widgets={
"df_annotations": {
"type": pn.widgets.Tabulator,
"editors": self.editors,
"widths": self.table_widths,
"show_index": self.table_show_index,
"height": self.table_height,
"layout": self.table_layout,
"pagination": self.table_pagination,
"page_size": self.table_page_size,
"selectable": "checkbox",
"sizing_mode": "stretch_width",
"margin": 2,
}
},
show_name=False,
)[0]
self._add_button = pn.widgets.Button(name="add", width=30, height=30,button_type = "primary")
self._add_button.param.watch(lambda evt: self.param.trigger("add"), ["clicks"])
self._remove_button = pn.widgets.Button(name="detete", width=30, height=30, button_type = "primary")
self._remove_button.param.watch(lambda evt: self.param.trigger("delete"), ["clicks"])
@param.depends("add", watch=True)
def _add_row(self):
assert isinstance(self._annotations_table.value, pd.DataFrame)
self._annotations_table.value = self._annotations_table.value.append(
self.new_row, ignore_index=True
)
@param.depends("delete", watch=True)
def _delete_row(self):
assert isinstance(self._annotations_table.value, pd.DataFrame)
self._annotations_table.value = self._annotations_table.value.drop(
self._annotations_table.selection
).reset_index(drop=True)
def __panel__(self):
return pn.Card(
pn.Row(self._add_button, self._remove_button),
self._annotations_table,
title=self.title,
collapsed=False,
**{
k: self.param.inspect_value(k)
for k in pn.viewable.Layoutable.param.params().keys() # type: ignore
if k not in ["css_classes", "name"]
}
)
editors = {
"start": {"type": "number"},
"end": {"type": "number"},
"type": SelectEditor(options=["Standard", "Outlier"]),
"use": SelectEditor(options=["Train", "Test", "Train&Test", "No Use"]),
}
ac = AnnotationCard(editors, sizing_mode="stretch_width")
template = pn.template.FastListTemplate()
ac = AnnotationCard(editors, sizing_mode="stretch_width", table_height=207, margin=(0,-7,0,5))
template.sidebar.append(ac)
template.show()

Doing so would unfortunately be very expensive.