Deleting a row from repeating panel

Hi guys!

I’ve been stuck for a couple of days now, on something I think should be fairly easy!
But I can’t get my head around it!

Iv’e been using a repeating panel to display rows of information. I wanted to add a remove button just like the “storing and displaying data” tutorial.

self.item.delete() throws errors at me like there is no tomorrow.
I feel like I am missing something very basic!

What I have tried:

def button_1_click(self, **event_args):
"""This method is called when the button is clicked"""
args = [self.item['period'],
        self.item['date'],
        self.item['shop'],
        self.item['amount']
       ]

anvil.server.call('delete_bill', args)

self.item.delete()
self.remove_from_parent()

Error:

AttributeError: 'dict' object has no attribute 'delete_$rw$'

I also tried something from this excellent post and other stuff to no avail. Is it possible to remove a row with multiple items in it?

Thanks in advance for your precious time! :slight_smile:

self.remove_from_parent() alone should do the trick if you are trying to remove the row from the repeating panel’s items.

1 Like

Oh! It works! Thanks a lot!
I feel kinda dumb!

Re-Re-Re-Reading the tutorial, I figured the self.item.delete() works good because the data table is accessible from the client side and there is a write back between the client and the data table! Is that right?

Thank you very much your time!

If you are binding live row objects from your DataTable to your repeating panel, you would need to call the .delete() method (which I believe you were trying to do) if you are trying to delete an actual row from your DataTable. Your error suggests that you were trying to call that method on a Python dictionary, but dicts do not have a delete method.

My suggestion doesn’t delete from your DataTable. It just removes a row from the repeating panel’s items.

If you do want to delete rows from your DataTable, I think you would have to refresh you data bindings after calling .delete on a live row (if doing so from the client). I almost never have live rows bound in the client as there are performance issues with this approach (due to server calls that happen in the background). Rather, I return a list of pure Python dicts to the client and use those in my repeating panels.

1 Like

Okay!! Thanks for explanation! That’s very interesting!
Actually I’m not live binding!

I forgot to explain that part.
This is what I’m doing to populate the panel.

# Any code you write here will run when the form opens.
while not anvil.users.get_user():
  anvil.users.login_with_form()
  
account = anvil.server.call('get_account')
self.repeating_panel_1.items = account

Calling the server to get the right stuff in the panel.
What are the best practices for adding and deleting stuff?

So we can expect performance issue with live-row on client side.
What are the options and the use cases?

Just a note in case I forget how to solve this…
I used data-binding for a repeating panel in a form. The dictionary binding the forms looked like

as_dict = { "name":name, [{"x":something1,"y":something2}{"x":something3,"y":something4}{etc}]}

Assign to forms:

self.item = as_dict

This did NOT work when trying to delete a item within a repeating panel:

def button_delete_click(self, **event_args):
  self.item.delete()
  self.remove_from_parent()

With the same error as @Vincent .

@stucork solved it for me using:

  def button_delete_click(self, **event_args):
    """This method is called when the button is clicked"""
    self.remove_from_parent()
    event_args['sender'].trigger('writeback')

Using the augment from anvil-extras.

I think there’s a bit of a misconception/mystery over self.item in repeating panels.

ALL that self.item is is an instance returned by the iterator that is passed to repeating_panel.items. So if you pass a SearchIterator (list of database rows) to a repeating_panel.items, then each ‘row’ has a self.item that is a RowObject, which happens to have a delete method (which as was mentioned will delete the row from the DataTable).

If you pass a list of dictionaries to repeating_panel.items, then each row is a dictionary and you can access values using the dict keys (similar to the behavior of the RowObject). But, you could not call delete because dictionaries don’t have a delete method.

As a fun experiment, pass a string to repeating_panel.items. You’ll find that each row’s self.item is a character - because when you iterate over a string you get a list of characters, and that’s ALL that is happening here!

Just to recap:
There’s nothing magic about self.item. It’s just the instance returned by that ‘iteration’ of the iterable passed to repeating_panel.items.

3 Likes