Hey everyone,
I have custom HTML cards that are populated on a repeating panel. I place them on a link then use the click method of the link to hide or show some elements (this basically expands and contracts the card). This works well, but I want the previous card to contract when I click on a different card, however I’m not sure how to refer to a specific repeating panel item or alternatively the item clicked before the current item. Is there a way to do this?
Here is a demo anvil app
https://anvil.works/build#clone:4MB6NZD4CHDQTGZM=YMW2ZNBY7RIE6BSN4RIBNOWD
Regards,
Stephan
In general, you should be able to do that by using self.parent.raise_event_on_children
and letting each card work out if it’s the one that’s supposed to be reacting. What information you pass into the event depends on the relationship between the card clicked on and the card that you want to react.
If, for example, you wanted the immediately previous card to react, you could pass the index of the current card in the repeating panel, and let all the cards compare themselves to it to see if they’re the immediately previous one.
I was thinking of doing that, but I’m not sure how to get the index when you click the card. I’m aware that you can loop through all the elements loaded from the database into the repeating panel, but I’m not sure how you can get the clicked card’s index. Any ideas on how to do that?
That depends on how you filled out your repeating panel’s items property. If it was filled out from a Python list, then this will give you the index of a card from inside that card:
index = self.parent.items.index(self.item)
If it was filled out from a search iterator, those don’t support the index method. The most brute force way of getting around that is to convert the search iterator to a list before assigning it to the repeating panel’s items property. That may or may not be suitable, depending on how much data there is in it.
Another option is to give each item an order
property that can work as an index. That means you have to maintain that order property, and sort by it when searching, etc. But once it’s there, each item will automatically know its order in the repeating panel. That works well when you’re not filtering the search results by anything that would change the order.
This works well to get the index, thank you very much! I’m still a little unclear on how to pass this information to the “self.parent.raise_event_on_children”, any tips on how to proceed there?
You pass keyword arguments to the events, e.g.:
index = self.parent.items.index(self.item)
self.parent.raise_event_on_children('x-your-event-name', index=index)
Then in the event handling function, add that parameter to the list:
def handle_foo(self, index, **event_args):
pass
You can put whatever check you want in there to see if the component that’s handling the event is supposed to react, based on the index passed in.
I got this part working i.e. referring to specific items from the repeating panel. However, I see now that it’s actually just referring to the rows that it pulls from the database. I need to access the components they are bound to i.e. the RichText in which the row data is displayed. However, I’m still at a loss on how to access that since the index of the parents items returns the row of data. Any idea how to access the components?
In your event handler just access the components, e.g.:
def handle_foo(self, index, **event_args):
self.rich_text_1
Thanks for all your help @jshaffstall, I eventually got it working. The tricky part was referencing certain components on the card because I didn’t want them all to hide when I clicked, so I had to specify. I realized that you can just loop through all the “children” of a parent component by using for loops and the get_components() method. In this way you can find the individual components and hide them one-by-one. I have included my code for you to see in case you were curious and for others facing a similar problem.
https://anvil.works/build#clone:4MB6NZD4CHDQTGZM=YMW2ZNBY7RIE6BSN4RIBNOWD
Regards,
Stephan
1 Like