Adding a data table link to a table which already contain another data table link:

Hello,

I’m current trying to build a card collection builder and I’ve ran into a problem which I cant seem to solve:

For some context, I have 3 data tables (Cards, Collections and Collections_content). My homepage shows all the names from the Collections data table. When you click one serie you will see a list from collections_content where the name equals the name you clicked and a search functionality which searches through the Cards data table.

The search results contain a button per result which gives you the ability to add that card to your collection. Im trying to figure out how I can add a link to the card in my Collections_ content so I can easily reference details(price, serie, etc). This means that the Collections_content data table will contain two columns (collection as a reference to Collection and cardLink as a reference to Cards).

I’ve tried the following but it’s not working:

In the server module:

@anvil.server.callable
def link_card(card):
  link = app_tables.cards.get(Name=card)
  return app_tables.collections_content.add_row(CardLink=link)

on the button:

  def button_1_click(self, **event_args):
    card_to_link = anvil.server.call('link_card', self.card_name.text)
    app_tables.collections_content.add_row(CardLink=card_to_link)

What am I doing wrong?

Here’s a link for anyone who wants to look:

https://anvil.works/build#clone:CUNLWTMN5XJYIHXS=LF6ZMGD6RXI4725UDVPJ7RFG

Thanks in advance for any help!

This function looks like it will correctly add a link to a card Row from collections_content:

@anvil.server.callable
def link_card(card):
  link = app_tables.cards.get(Name=card)
  return app_tables.collections_content.add_row(CardLink=link)

It returns a Row from the collections_content table.

It looks like the problem is in your click handler. card_to_link is actually a Row from the collections_content table, but you’re trying to add it to the CardLink column.

  def button_1_click(self, **event_args):
    card_to_link = anvil.server.call('link_card', self.card_name.text)
    app_tables.collections_content.add_row(CardLink=card_to_link)

From what you’ve said, it sounds like you want to simply call your server function from the click handler:

  def button_1_click(self, **event_args):
    anvil.server.call(
      'link_card', self.card_name.text, self.collection_name.text
    )
    # ... that's all we do here

But make the server function add a link to the collection as well as the card (notice I passed in self.collection_name.text from the click handler, imagining you’ve got a textbox for that) .

@anvil.server.callable
def link_card(card, collection):
  link = app_tables.cards.get(Name=card)
  collection = app_tables.collections.get(Name=collection)
  return app_tables.collections_content.add_row(
    CardLink=link,
    CollectionLink=collection
  )

Best practice would be to put this in a transaction so the database operation can rollback if anything changes the data under its feet.

@anvil.server.callable
@tables.in_transaction
def link_card(card, collection):
  link = app_tables.cards.get(Name=card)
  collection = app_tables.collections.get(Name=collection)
  return app_tables.collections_content.add_row(
    CardLink=link,
    CollectionLink=collection
  )

Thanks for the help so far. The code makes sense but I cant seem to get the link to the collection_name to work. I actually dont have a textbox for that, it’s being send to the page with the following code from the homepage:

  def link_1_click(self, **event_args):
"""This method is called when the link is clicked"""
open_form('Collection', item=self.item)

In this case the collection_name would be self.item[‘Name’].

I’m having trouble accessing this data in the function for adding it. I’ve tried the .parent and other codes but my knowledge of talking between forms is lacking (read other topics about it but still can’t figure it out). The code is in a button in the repeating pannel(ItemTemplate) and the collection name is in “main page” which contains the form. How do I communicate this data to the ItemTemplate?

As a bonus question which is closely related:

If I click the add button, how can I update a different repeating panel/data grid which is on the same page but not in the same form?

Thanks in advance!

Hi there.

If you are looking to access the data that you passed to the “Collection” form, you will find it under properties in the init method (e.g., properties['item']['Name'])

For example:

class Collection(CollectionTemplate):
  def __init__(self, **properties):

    # Set Form properties and Data Bindings.
    self.init_components(**properties)
    
    print(properties['item']['Name']) # here is the data you passed along when you opened this form

   .
   .
   . 

Also, in general, when you are inside a RepeatingPanel’s ItemTemplate, there are various ways of reaching back to the “outside” (i.e., parent forms). Perhaps the discussions below can help explain a few approaches.

Thanks! I got it to work using .parent five times is a row. Not sure if that is the cleanest code but at least it works :smiley:

Hi there - don’t do that :slight_smile:

Whilst it might work now, it won’t take much to break it. Is there an anchor point? For example, the main open page can be accessed with get_open_form().

If not, could you store the form in a property on that main form? For example :

# Set form reference.
get_open_form().my_form_reference = Form3()
# Read it from anywhere -
get_open_form().my_form_reference.repeating_panel_1 = my_item_array

Chained parent references are messy and will almost certainly cause hard to find issues in the future, as well as being unwieldy and difficult to understand in 6 months time.

3 Likes

THIS!

I use this approach in nearly every app (thanks to some good advice)

1 Like

Thanks this gave me a much butter understanding of how to access elements outside a form which I’ll be using a lot!

1 Like

4 posts were split to a new topic: Change a property a parent form when clicking a nested link