When I do my_tabulator.value = my_df with new data frame data, the columns do not resize to fit the new data. I have found a workaround where I populate it with an empty dataframe, then populate it with the new data, but that has been causing weird behaviors lately. I can’t seem to find any info anywhere about this. Is there a solution to this?
Can you share a minimal example? Thanks!
def pop_table(self, id=None, filters=None):
self.df = self.crud_manager.custom_df(filters=filters)
self.table.value = self.df
Sorry I meant a fully runnable, copy-pastable example with minimum dependencies
sorry. That was not minimal. Let me make one
import panel as pn
import pandas as pd
from random import randint
# Enable Tabulator extension
pn.extension('tabulator')
# Sample initial data
data = {'Name': ['Alice', 'Bob', 'Charlie'], 'Age': [24, 30, 22]}
df = pd.DataFrame(data)
# Class definition
class SimpleTabulatorApp:
def __init__(self):
# Define the Tabulator widget with the initial DataFrame
self.tabulator = pn.widgets.Tabulator(df, height=300, width=400)
# Define the Button widget
self.button = pn.widgets.Button(name='Update Data', button_type='primary')
# Set up the on_click method for the button
self.button.on_click(self.update_data)
# Layout for the app
self.layout = pn.Column(self.tabulator, self.button)
# Method to update the DataFrame and repopulate the Tabulator
def update_data(self, event):
# Update the DataFrame with new random ages
new_data = {'Name': ['Alice', 'Bob', 'Charlie with a Long Last name'], 'Age': [randint(20, 40) for _ in range(3)]}
new_df = pd.DataFrame(new_data)
# Repopulate the Tabulator with the updated DataFrame
self.tabulator.value = new_df
# Method to display the app
def show(self):
return self.layout
# Instantiate the app
app = SimpleTabulatorApp()
# Display the app
app.show().servable()
Thanks for the MRVE. Here’s a workaround to use placeholder. Otherwise, you may want to report it on GitHub issues.
import panel as pn
import pandas as pd
from random import randint
# Enable Tabulator extension
pn.extension('tabulator')
# Sample initial data
data = {'Name': ['Alice', 'Bob', 'Charlie'], 'Age': [24, 30, 22]}
df = pd.DataFrame(data)
# Class definition
class SimpleTabulatorApp:
def __init__(self):
# Define the Tabulator widget with the initial DataFrame
self.placeholder = pn.pane.Placeholder()
tabulator = pn.widgets.Tabulator(df, height=300, width=400, layout="fit_data")
self.placeholder.object = tabulator
# Define the Button widget
self.button = pn.widgets.Button(name='Update Data', button_type='primary')
# Set up the on_click method for the button
self.button.on_click(self.update_data)
# Layout for the app
self.layout = pn.Column(self.placeholder, self.button)
# Method to update the DataFrame and repopulate the Tabulator
def update_data(self, event):
# Update the DataFrame with new random ages
new_data = {'Name': ['Alice', 'Bob', 'Charlie with a Long Last name'], 'Age': [randint(20, 40) for _ in range(3)]}
new_df = pd.DataFrame(new_data)
# Repopulate the Tabulator with the updated DataFrame
tabulator = pn.widgets.Tabulator(new_df, height=300, width=400, layout="fit_data")
self.placeholder.object = tabulator
# Method to display the app
def show(self):
return self.layout
# Instantiate the app
app = SimpleTabulatorApp()
# Display the app
app.show().show()
I might be a little late on this one but I had a similar issue and found another workaround.
You can introduce a layout change after your tabulator update in order to trigger Tabulator’s autoResize. If your standard layout is “fit_data_table” then it would look something like this:
tabulator = pn.widgets.Tabulator(df, layout="fit_data_table", configuration={"autoResize": True})
def callback(event):
tabulator.layout = "fit_data"
tabulator.layout = "fit_data_table"
Thanks for sharing! Can you share this as a Panel issue as well? Maybe we can just build this in (if there are no downsides).
Hi! You mean on Github?
Sadly, there are minor drawbacks with my approach:
- You cannot use the arrow keys properly in the Tabulator (like in an Excel sheet for example) if you use it with on_edit or on_click . You always have to click on a new cell once you entered something, which can be quite annoying if the user wants to enter a lot of data him- or herself. Please correct me if I am wrong but I presume this is the case for your solution as well. In such cases I would suggest to not integrate the layout update callback. Instead, the user should know that he/she can e.g. just resize one column with his/her mouse and all other columns will resize automatically.
- Double update of the layout as in my example before leads to some weird “screen flickering”. This can be remedied by only inducing an update once and altering between layouts that are acceptable. In my case, “fit_data” and “fit_data_table” both yield the same result, so I used:
def callback(event):
if tabulator.layout == "fit_data":
tabulator.layout = "fit_data_table"
else:
tabulator.layout = "fit_data"
Yup Panel GitHub