Auto-add checkbox to every repeating panel row?

Anvilites, hopefully a simple dumb noobq, I have a repeating panel, done by the book, by the tutorial, and it works fine.

Now I want to add a checkbox on every row of this table, which may be reloaded time to time with varying numbers of rows. I looked at the ‘checkbox’ article in the dox, and also at the various datagrid tutorials, but I did not see how to do two things:

  1. automatically have a checkbox added to the left side / first column of every repeating row, whenever the table is reloaded, with no manual insertion of checkbox on each row.

  2. Once each row has its checkbox, how to I grab the one(s) that are in fact checked by a user, how do I refer to each rows box?

Somebody must have done this already? Thank you very much in advance!

For the native DataGrid component you’ll want to include an initial column.
Then add a checkbox component inside the RowTemplate

Assuming you want the action to get the selected rows on a button click
inside the main form you can do something like this


class Form1(Form1Template):
    ...

    def get_selected_rows(self):
        selected = []
        for row_template in self.repeating_panel_1.get_components():
            if row_template.check_box_1.checked:
                selected.append(row_template.item)
        return selected
        
    def button_click(self, **event_args):
        selected = self.get_selected_rows() 
        ...

Note: the above will only get the selected items on the current page
If you want the selected items across all page you’d probably want the checkbox change event to communicate its state. (possibly by raising an event on the parent)

    def check_box_change(self, **event_args):
        self.parent.raise_event("x-selection-change", item=self.item, selected=self.check_box_1.checked)

and then in the main form

    def __init__(self, **event_args):
        self.repeating_panel_1.set_event_handler("x-selection-change", self.selection_change)
        self.selected_items = set()

    def selection_change(self, item, selected, **event_args):
        "add or remove an item from the list of selected items"
        if selected:
            self.selected_items.add(item)
        else:
           self.selected_items.discard(item)



Also a tabulator version

You might also end up exploring the Tabulator dependency which might look something like this:


from tabulator.Tabulator import row_selection_column


class Form1(Form1Template):
    def __init__(self, **properties):
        ...

        self.tabulator_1.columns = [
            row_selection_column,
            {"title": "Name", "field": "name"},
            ...
        ]

        self.tabulator_1.options = {
            "app_table": app_tables.my_table,
            "pagination": False,
            "progressive_load": True,
            "progressive_load_delay":200,
        }

    def get_selected_rows(self):
        tabulator_rows = self.tabulator_1.get_selected_rows()
        return [row.get_table_row() for row in tabulator_rows]
        

    def button_click(self, **event_args):
        selected = self.get_selected_rows()
        ...


clone:
https://anvil.works/build#clone:3ZT6VF4P3SOZJVO4=RYVPHN5QMWXAOVFQTI37LQP2

2 Likes

Wow slick, thank you very much, I will try all!

1 Like

@stucork: thank you so much for your example! I just ran into the problem, that the code does not deliver all rows if the repeating panel has several pages. If it has several pages the example only provides the rows of the current page. Would really appreciate if you would have a solution for this one as well. I modified your code a bit tp show the eample:

https://anvil.works/build#clone:WVL7CLOPFXMJDPIT=B47TCNBW7C6GTT5Z24E2XBAB

@bluefrog - The full solution above includes a code snippet/explanation for how to implement the idea across all pages.

The clone link is only for the initial idea (i.e. the current page).
Which part are you struggling to implement in your own code?

You’ll need to add the event handler for the check box on the repeating panel (code as above).
Then include the code on the main form (also above).

The button handler for getting selected rows will then look something like this:

    def button_click(self, **event_args):
        selected = self.selected_items
        ...

@stucork - Thanks for helping! I was hoping that there would be a solution similar to the clone link. Like: getting all selected items by iterating through all pages of the panel and not only the current page. If this is not possible I will implement the event handler solution.

1 Like