Question on custom event handlers

What I’m trying to do:

I’m trying to create links dynamically (in code), assign a common link_click event handler, and then in the event handler, “know” which dynamically-created link triggered the click event.

What I’ve tried and what’s not working:

This works (see clone as well), but when I try to pass that event handler arguments that might identify the triggering link, whether I put all that in the init or form_show… if there are arguments in the event handler specification then, the event handler fires every time I add the component.

from ._anvil_designer import Form1Template
from anvil import *

class Form1(Form1Template):
  def __init__(self, **properties):
    # Set Form properties and Data Bindings.
    self.init_components(**properties)


  def form_show(self, **event_args):
    data=['Choice 1','Choice 2','Choice 3', 'Choice 4', 'Choice 5']
    
    for company in data:
      link = Link(text=company,align='center',tag=company)
      link.set_event_handler("click", self.eventHandler(link.tag))   
      self.add_component(link)
  
  def eventHandler(self, source, **event_args):
    print("which code-created link was clicked to display me?")
    print(source)

Clone link:
https://anvil.works/build#clone:NBDJDBOBQAEGVJZZ=EOJARFH3MDF32YZN6QHW45OI

Just looking quickly but it seems that you are actually calling the link’s event handler when you are attempting simply pass it as an argument.

Try just using …

link.set_event_handler(“click”, self.eventHandler)

Notice the lack of parentheses when passing the function as an argument.

Yep - that works. However, then when I click a link, in the event handler… how can I know which link triggered the click event?

You can examine the tag attribute from within the callback function.

event_args[‘sender’] is the component that was clicked.

Docs:

1 Like

It’s worth noting that event_args[‘sender’] is the component the event handler was set on. In this example that’ll also be the link that was clicked, but in more complicated setups that might not be the component that was actually clicked.

1 Like

i often change me call signatures when sharing an event handler across different components

    data=['Choice 1','Choice 2','Choice 3', 'Choice 4', 'Choice 5']
    
    for company in data:
      link = Link(text=company,align='center',tag=company)
      link.set_event_handler("click", self.event_handler)   
      self.add_component(link)
  
  def event_handler(self, sender, **event_args):  
    # include the sender in the call signature
    print("which code-created link was clicked to display me?")
    print(sender.tag)

It’s basically the same as using event_args['sender'] but occasionally more convenient.

You can no longer just call event_handler as a raw function (unless you provide it with a sender as an argument) - which is good if you need sender.tag.
You can still call it via - self.link_1.raise_event('click') where self.link_1 will become the sender

3 Likes