Tabulator columns not resizing after re-populating with new data

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"
1 Like

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:

  1. 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.
  2. 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