How to access the data in Tabulator's row_content?

Hi,

I used the row_content argument in Tabulator to create sub-tables for each row in a tabulator. Now I am trying to access the content in the sub-table (e.g. edit the value of sub-table and save the record). I was wondering if there’s any way to do it.

This is an example.


import pandas as pd
import random
import panel as pn

pn.extension('tabulator')
class Example:
    def __init__(self):
        self.countries = ['US', 'Canada', 'Mexico'] * 3
        self.years = [2023, 2023, 2023, 2022, 2022, 2022, 2021, 2021, 2021]
        self.ratings = [random.uniform(0,100) for _ in range(9)]
  
        self.data = pd.DataFrame({'Country': self.countries,
                            'Year' : self.years,
                            'Rating': self.ratings})
  
        self.select = pn.widgets.Select(name='Select Country', options=['US', 'Canada', 'Mexico'])
        self.button = pn.widgets.Button(name='Gnenerate Table')
        
        self.content_fn = lambda row: pn.widgets.Tabulator(
            self.data[self.data['Year']==row['Year']]
        )
        
        self.table = pn.widgets.Tabulator(pd.DataFrame(), row_content=self.content_fn, embed_content=True) # 
        
        self.button.on_click(self.generateTable)
        
 
    def generateTable(self, var):
        countrySelect = self.select.value
        df = self.data[self.data['Country']==countrySelect]
        self.table.value = df 
  
e = Example()
  
pn.Column(e.select,
          e.button,
          e.table)

screenshot_panel

Let’s say I want to update the rating in the sub-table for country Canada year 2023 and access the new rating. Is there any way I can do that?

Thanks in advance. Any advice would be appreciate it!

Hi @ssypangpang

Welcome to the community.

One way to do this is to add an on_edit callback function. The callback function will be given an event holding information about which cell changed and what the change was.

import pandas as pd
import random
import panel as pn

pn.extension("tabulator")


class Example:
    def __init__(self):
        self.countries = ["US", "Canada", "Mexico"] * 3
        self.years = [2023, 2023, 2023, 2022, 2022, 2022, 2021, 2021, 2021]
        self.ratings = [random.uniform(0, 100) for _ in range(9)]

        self.data = pd.DataFrame(
            {"Country": self.countries, "Year": self.years, "Rating": self.ratings}
        )

        self.select = pn.widgets.Select(
            name="Select Country", options=["US", "Canada", "Mexico"]
        )
        self.button = pn.widgets.Button(name="Generate Table")
        self.log_pane = pn.pane.Markdown()
        self.table = pn.widgets.Tabulator(
            pd.DataFrame(), row_content=self.content_fn, embed_content=True
        )  #

        self.button.on_click(self.generateTable)

    def generateTable(self, var):
        countrySelect = self.select.value
        df = self.data[self.data["Country"] == countrySelect]
        self.table.value = df

    def content_fn(self, row):
        tabulator = pn.widgets.Tabulator(
            self.data[self.data["Year"] == row["Year"]], margin=(50,10,10,10)
            
        )
        tabulator.on_edit(self.log)
        return tabulator

    def log(self, event):
        country = self.data.at[event.row,"Country"]
        year = self.data.at[event.row,"Year"]
        if event.column=="Rating":
            self.log_pane.object=f"**{country}, {year}: {event.old:.2f} -> {event.value:.2f}**"



e = Example()

pn.Column(e.select, e.button, e.table, e.log_pane).servable()

1 Like

Works like a charm. Thanks so much @Marc for the prompt response - really appreciate it!!

1 Like