Switching between tabulators trims the table when it contains images

Hello All,

I have one select widget in sidebar, which controls which tabulator appears in main view.
My tabulator has images within it and when switching from one to another, the layout is trimmed.

As an example, the table should be:

but instead when refreshing and switching to a different tabular, it gets to this:

Here is the code to reproduce this:

import panel as pn
import pandas as pd

pn.extension("tabulator")


def create_report(stage):
    demo_df = pd.DataFrame(
        data={
            'Steps': [f'Step {stage}{i + 1}' for i in range(5)],
            'Actions': [f'Perform step {stage}{i + 1}' for i in range(5)],
            'Images': [f'assets/demo_images/Image{stage}_{i + 1}.png' for i in range(5)],
        },
        index=[i + 1 for i in range(5)]
    )

    tabulator_formatters = {
        'Images': {'type': 'image'}
    }

    df_table = pn.widgets.Tabulator(
        demo_df,
        header_align='center',
        text_align='center',
        selectable=False,
        theme='simple',
        formatters=tabulator_formatters,
        show_index=False,
    )

    stage_report = pn.Column(
        f'## Report stage {stage}',
        df_table
    )

    return stage_report


select = pn.widgets.Select(name='Select stage', options=['A', 'B'])
report = pn.bind(create_report, stage=select)

template = pn.template.FastListTemplate(
    site="Staging reports",
    title="",
    theme_toggle=False,
    header_background="rgb(95,158,209)",
    sidebar=[select],
    main=[report]
)

template.servable()

Thank you for any suggestions!

Regards, Sorin

Bug

I’ve reported it as a bug here Tabulator does not resize to fit content · Issue #3847 · holoviz/panel (github.com).

Workaround

You can try setting the width in the tabulator_formatters

 tabulator_formatters = {
        'Images': {'type': 'image', 'width': 200}
    }

and/or the height, width and sizing_mode of the df_table Tabulator table and the stage_report Column.

For example this is a combination that might work for you.

import pathlib

import pandas as pd
import panel as pn
from PIL import Image, ImageDraw

pn.extension("tabulator")

ROOT = pathlib.Path(__file__).parent
N = 5

def image_path(stage, i)->pathlib.Path:
    return ROOT/f"assets/demo_images/Image{stage}_{i + 1}.png"

def create_images():
    for stage in ["A","B"]:
        for i in range(N):
            path = image_path(stage, i)
            if not path.exists():

                img = Image.new('RGB', (200, 200), color = (73, 109, 137))
            
                d = ImageDraw.Draw(img)
                d.text((20,20), "Hello World", fill=(255,255,0))
                path.parent.mkdir(exist_ok=True, parents=True)
                img.save(path)

create_images()

def create_report(stage):
    demo_df = pd.DataFrame(
        data={
            'Steps': [f'Step {stage}{i + 1}' for i in range(N)],
            'Actions': [f'Perform step {stage}{i + 1}' for i in range(N)],
            'Images': [f'assets/demo_images/Image{stage}_{i + 1}.png' for i in range(N)],
        },
        index=[i + 1 for i in range(N)]
    )

    tabulator_formatters = {
        'Images': {'type': 'image', 'width': 200}
    }

    df_table = pn.widgets.Tabulator(
        demo_df,
        header_align='center',
        text_align='center',
        selectable=False,
        theme='simple',
        formatters=tabulator_formatters,
        show_index=False,
        height=800,
        sizing_mode="stretch_width"
    )

    stage_report = pn.Column(
        f'## Report stage {stage}',
        df_table, sizing_mode="stretch_width",
    )

    return stage_report


select = pn.widgets.Select(name='Select stage', options=['A', 'B'])
report = pn.bind(create_report, stage=select)

template = pn.template.FastListTemplate(
    site="Staging reports",
    title="",
    theme_toggle=False,
    header_background="rgb(95,158,209)",
    sidebar=[select],
    main=[report]
)

template.servable()
panel serve 'script.py' --auto --static-dirs assets=assets

1 Like

Thank you for your suggestion, @Marc!
In my case, the images’ dimension is not the same between the reports (even in the same report) - I’ll have to update the tabulator_formatters between the reports and maybe consider some level of resizing the images to at least have same width or height.
If is ok, I will keep this topic open, until I am able to share more info on my progress using your workaround.

1 Like

I tried several combinations using height, width and sizing_mode but I was not able to find a combination that would work for this case.

1 Like

Hi @sorin

If you can add your minimum, reproducible example in the bug report above (including working links to relevant images) then it would be possible for someone (some day) to fix.

1 Like