New: A more Pythonic way to handle events

Introducing the @handle decorator

We are changing the way event handlers work in Anvil! In Form code, methods that are registered as event handlers will now be decorated with @handle("<component_name>", "<event_name>"). This new decorator makes it explicit in code which methods are event handlers for which components.

You can set event handlers in code by decorating them with @handle, and when you create an event handler from the Anvil Designer (using the Object Palette or the Properties Panel), the method that is set up for you will have this decorator.

Here’s an example click event handler for a Button called submit_button:

@handle("submit_button", "click")
def submit_button_click(self, **event_args):
    """This method is called when the button is clicked"""
    anvil.server.call("submit_form", self.item)
    self.submit_button.text = "Submitted!"

Setting event handlers in code

It’s a lot smoother to set and modify events handlers decorated with @handle. Just add the decorator to a function in your Form code and give it the name of the component and the event you want to raise: @handle("<component_name>", "<event_name>")

Your function can have any name, but should have **event_args as one of its parameters.

Modifying event handlers

The @handle decorator also makes it simple to modify existing event handlers. Want to bind the handler to a different component? Just change the component name in the decorator! The same goes for if you want to change the event that triggers the function.

It’s easier to see existing event handlers

The @handle decorator makes it a lot easier to know which components are connected to which event handlers because it’s all explicit in the code. You no longer have to scroll to the bottom of the Properties Panel to see the event handlers that a component raises.

Things to note

Existing event handlers in existing apps will not change. The new decorator will only be added to newly created events. You can easily update an existing event handler to use @handle by deleting the name of the event handler from the Properties Panel and re-adding it by clicking the blue arrow.

When an event is decorated with @handle, it will show up at the bottom of the Properties Panel as expected. However, you will not be able to modify the event from here. If you want to modify the event or delete it completely, you’ll need to do this in code.

Happy event handling!
Brooke

11 Likes

Undocumented:

    @handle("button_1", "click")
    @handle("button_2", "click")
    def any_button_click(self, **event_args):
        """This method is called when the button is clicked"""
        pass

works! You may have to add the 2nd @handle manually.

Nice catch - although we mentioned it in the announcement blog post, it was missing from the docs.

Stacking @handles is a neat technique everyone should know about, so I’ve added it there too :slight_smile:

2 Likes

Absolutely!

In my case, it’s usually not the event that varies from one line to the next, but the component. But it works in both cases.

This is so great, I just realized you can change the name of the function without having to change things in the editor!

3 Likes