Tabulator: Which column am I in?

What I’m trying to do:
Get some design-time information, to plan my first use of Anvil Tabulator.

I have cells that need to be disabled or disappear (because there is supposed to be no data at their location). It seems easiest to do this by supplying an Anvil form to display in those columns, as the column’s “cell editor”.

But there will be two or more such columns, and the form will therefore need to be told which column it’s in. Somehow.

Question is here

but it might be useful to expose it on this Forum, too.

What I’ve tried and what’s not working:
Using a copy of the Tabulator Example, I looked in the form’s self.items and **properties. Aside from the values in the current row, no context information seems to be available. Or, if it is available, it’s not obvious how to find it.

Here is a method I add to the tabulator cell_click event

  def cell_click(self,cell, **event_args):
    field    = cell.get_field() #Column Name
    row      = cell.get_row()  #Tabulator Row
    row_data = row.get_data() #Dictionary of Tabulator Row
    self.edit_map[field](row,row_data)

Let’s think this through, with the Example App: Example App

By the time the instance of FavColorCell comes into existence, the proposed cell_click has already occurred. We can’t register FavColorCell’s cell_click handler to handle it.

We can register something else’s cell_click handler. But then the self receiving the event is some other object. The instance of FavColorCell, which is the self that needs to know, won’t be receiving this information.

However, the cell_click handler might stash that information somewhere, where the FavColorCell can find it. If we assume that there can be only one FavColorCell in existence at any one time, then this might work.

I see.

So this post is more in line with this discussion:

My apologies I read the github discussion (at the top of this thread) and answered that question more than the disabling a cell.

In the following clone, I added an ‘editable’ check and disabled the “Favorite Color” column if the color was yellow.

Here is the column setup:

{"title": "Favourite Color", "field": "col", "editor": FavColor,'editable':self.check_if_editable},

and here is the method:

    def check_if_editable(self,cell,*args,**params):
      data = cell.get_data()
      return data['col'] != "yellow"

I used cell.get_data() instead of cell.get_value() because that has given me issues in the past.

No need to apologize, friend. You were correct the first time. My other GitHub discussion post (“Disabling specific cells”) is indeed a separate question. And I appreciate having an answer for it! I’m trying it out now.

Edit 1
It gets me the data I need to decide whether to enable editing. Thank you!

Edit 2
This led me to the Cell Callbacks documentation: Callbacks | Tabulator

Specifically, the cellEditing callback. With this, I can set a shared (global-lifetime) variable to the column name, and capture that value in FavColorCell.__init__()

column_name = None

def on_before_edit(cell):
    global column_name
    column_name = cell.get_field() #Column Name

class FavColorCell(FavColorCellTemplate):
    def __init__(self, **properties):
        self.column_name = column_name
        self.init_components(**properties)

There’s a small window of opportunity for something else to change column_name, but it’s a very small window, so it’s probably not worth worrying about.

1 Like

Given that you’re working with user interface code here, and specifically when the cell is edited, I think you’re likely right that the chance of anything else modifying that global is slim.

But, it makes me cringe to see the code.

1 Like

In this scenario, what would be the benefit to having a shared global column_name variable? (strictly asking to understand the application and maybe apply it to my codebase)

Thinking out loud section

Is it this part of the original post?

[quote=“p.colbert, post:1, topic:16645”]
But there will be two or more such columns, and the form will therefore need to be told which column it’s in. Somehow.
[/quote]‘’

So you will have multiple columns use the same editing form? So then you set the global variable with the callback? and that will update the forms self.column_name variable to be used in its methods.

1 Like

Me too. It would be better for the form to receive that information as an argument.

Yes, that’s the right part. I’ll be creating a table with multiple columns, all of the same type and behavior. Their editors should be all of the same Form class.

No, the callback updates only the global variable. self.column_name gets created from that, but never gets updated. On purpose.

This works because Tabulator uses only one “editor” component at a time, for each table, and creates it as a (short-lived) object, on demand. Thus, for a given table, there should be only one instance of my form in existence at any one time. For the lifetime of that instance, it is bound to exactly one cell. That instance dies when focus leaves the cell.

1 Like

Ahhhhh, okay. Thank you!

Tabulator documentation states the cell object should be available to the editor function as a argument, but I think the library does some magic for us that makes the argument just the row data.

Yes. **properties contains items, but currently that’s it. More context would be helpful in this case. Maybe in some future version of the wrapper…

1 Like

You should now get the cell as part of the properties in the latest version.

3 Likes

Beautifully simple! And it opens so many doors… especially for those (like me) still trying to wrap my head around Tabulator JS.

Compared to the object-oriented GUIs I’ve learned over the last 3 decades, Tabulator JS takes such a different approach, I’ve found it hard (for me) to design with. This helps. A lot.

Thank you, @stucork!