Referencing parents/childern

What’s the best way to reference parent forms or other elements when using a DataGrid?

I have a form with a DataGrid on it, and within its Repeating Panel: Data Row Panel (another form) is a TextBox. On the lost_focus event of this Text Box I’d like to refresh the Totals label in DataGrid’s Column Panel (at the bottom).

It’s usually best to keep all knowledge of a Form’s structure within the Form itself, so if the Form structure changes, all the code that needs to change is within the Form.

This can usually be achieved with get_open_form().

In your case, you could create an event handler on the Form that knows how to update the Label:

# In the main Form
  def __init__(self, **properties):
    # ...
    self.set_event_handler('x-update-label', self.update_label)
    
  def update_label(self, new_text, **event_args):
    self.label_1.text = new_text

Then raise the event from the lost_focus event:

# In the Data Row Panel
  def text_box_1_lost_focus(self, **event_args):
    """This method is called when the TextBox loses focus"""
    get_open_form().raise_event('x-update-label', new_text=self.text_box_1.text)

So the Data Row Panel is responsible for the TextBox within it, and the Form is responsible for the Label.

3 Likes

Excellent, thanks. What if the DataGrid is on the form, which itself is contained within the content_panel of the “main form”? I set up the event triggering on the form which as DataGrid on it (as you described), I even used the

get_open_form().raise_event_on_children('x-update-label')

but the refresh doesn’t happen.

You need to use raise_event rather than raise_event_on_children. The Label is an attribute of the Form, not the Data Grid, so the event needs to be a method of the Form itself.

1 Like

Actually, I had to use

get_open_form().content_panel.raise_event_on_children('x-update-label')

since the DataForm is on a form which is in the content_panel of the “main” form. Obviously, get_open_form() gets the topmost form and you still have to ‘traverse’ through all the hierarchy.

3 Likes

The Anvil event system seems limiting to me: you need to know beforehand who will handle the even. In this example one gabs the open form and raise an event on that. To me that is equivalent to calling a method on that form, like:

get_open_form().update_label(self.update_label)

If OTOH the event would be transmitted to all components, then any component might react to the event. But that is not the case, the only options are raise on 1 component or raise on the children of a component. There is no event bubbling AFAICT.

1 Like

I put something together recently to handle this kind of problem:

4 Likes