Addressing programatically added components

Good Morning!

Ever since I am using Anvil, I struggle with addressing programatically added components. The most common case is for me is adding a component in __init__ and them want to call refresh_data_bindings on it. I would like to do this as the components have their own __init__ functions with database calls. Example:

def __init__(self, **properties):
    self.init_components(**properties)
    child= Form3()
    self.add_component(child)

[...]

def button_3_click(self, **event_args):
    self.child.refresh_data_bindings() 
    # Returns AttributeError: 'Form1' object has no attribute 'child'

Such things work fine if the component is added in the editor as they can then be addressed as an attribute of the parent such as parent.child.refresh_data_bindings.

It also works if the child is added and addressed within the same method, such as:

  def button_2_click(self, **event_args):
    child = Button(background='maroon')
    self.add_component(child)
    time.sleep(1)
    child.remove_from_parent()
    # This works fine.

This question already addresses the question but as the thread opener sought to remove the component he added and hence could resort to clear() a named wrapper component.

I tried to use custom events but couldn’t make it work.

Maybe it’s some fundamental thing about Anvil architecture that I don’t understand?

Looks like this is just a Python syntax issue! When you do:

child = Form3()

…you create a local variable, which goes away as soon as you return from your function. This is why you can’t access it from button_3_click().

What you want to do instead is:

self.child = Form3()

Instead of creating a local variable, this version sets an attribute on self - that is, your form object. You can then retrieve this value in any other function with access to that object (eg button_3_click(), in your case).