What I’m trying to do:
I’d like to handle an event that a custom component raises in the parent component.
What I’ve tried and what’s not working:
In the child component, I’ve tried having the button raise an event like this button.raise_event('x-foo-event')
as well as doing an intermediary “click” event
In the parent form, I’ve tried using an set_event_handler on the form self.set_event_handler('x-foo-event', self.handle_event)
and by setting an event_handler on the child component comp.set_event_handler('x-foo-event', self.handle_event)
handle_event doesn’t seem to run in any of the combinations I tried.
From what I understand, events should be the best way to have forms communicate with one another. My guess is I’m missing some small piece here.
I’ve tried searching the Q&A forum for questions like “event handled in different form” and haven’t been able to find answers. If you have suggestions for better keywords when searching the forum, I would super appreciate that as well
You need to raise the event in the custom component from self (that is the custom component itself), not from the button – raising it from self from the button click handler was a good choice though!
You need to register the event on the component that is in the form, not the parent form itself (so comp in your example, not self)
You don’t nedd to register the event in the custom components properties if you will use an event that starts with x-. This prefix is made so you don’t need to do it. Also, if you register the event in the custom component, you don’t need to make your event start with x-. So you can either raise x-foo-event for an event that is not registered (or most of the time from a component that is not custom and you can’t control their events) or register and raise a foo-event. If this is your custom component and you will ofter trigger it, the best approach is obviously using a registered event, since it’s clearer.
As @duncan_richards12 said, you need to raise the event from the form itself, not the button. raise-event sends a message to the component’s parent. So self.button.raise_event('x-foo-event', value=foo) just sent foo to self. One thing that is good to check if it’s correctly sending to where you want is to check who is the component’s parent property, since he is who is getting the event. This is useful because if you did this, you would see that self.button.parent was <CustomComponent>, not <Form>, but self.parent was <Form> as expected.
This is important specially when you want a datagrid row to comunicate with the main form. The most intuitive thing to think (at least to me it was) is to bind the event_handler to the grid itself, but the parent of each row is the repeating_panel inside the data_grid. And I just realized this when I printed the self.parent inside a DataGridRow.
Thank you for helping me understand how these forms communicate with each other. It seems like events are meant for communicating between parent form and child form, is that an accurate understanding? The message module that @owen.campbell mentions is the tool that allows arbitrary forms to communicate with each other.
Just for my own curiosity - what does “anvilistas” mean? I know there is a fantastic collection of libraries oh github under that org. My brain keep parsing it as “Anvil is T[ool] A[ssisted] S[peedrun]” and I doubt that’s it.
Just so I understand fully… Events are for parents and children components to communicate.
Even if the callee can be any function or in any form, raise-event only ever sends a message to the parent and raise_event_on_children only ever sends the message to direct children of the component.
It raises the event on whichever component you choose. In your case, the parent is the appropriate component. That is probably the most common case, but certainly not the only one.
In more deeply-nested cases, it might be an ancestor further back, or a “cousin”. It’s not hard to imagine notifying some other component entirely, if that’s your “designated dispatcher” for that event.
To add on, events are also for triggering certain actions within a component: for example a.raise_event might trigger a color change for a and likewise if it were for b.raise_event