google / mesop

Rapidly build AI apps in Python
https://google.github.io/mesop/
Apache License 2.0
5.53k stars 265 forks source link

Event type changes when handler is shared #1094

Open pokutuna opened 16 hours ago

pokutuna commented 16 hours ago

Describe the bug

When same handler is used for both a shortcut and button click, pressing Ctrl+Enter unexpectedly triggers a ClickEvent instead of TextareaShortcutEvent.

This is confusing because the handler's expected event type (TextareaShortcutEvent) is overwritten by ClickEvent from later registration.

To Reproduce Steps to reproduce the behavior:

  1. Run this code:
import mesop as me

@me.stateclass
class State:
    event_type: str = ""

def submit(e: me.TextareaShortcutEvent):
    state = me.state(State)
    state.event_type = str(type(e))
    # Cannot access e.value with ClickEvent

@me.page(path="/page1")
def page1():
    state = me.state(State)
    me.textarea(
        placeholder="Ctrl+Enter to submit",
        shortcuts={
            me.Shortcut(ctrl=True, key="Enter"): submit,
        },
    )
    me.text(state.event_type)
    # => <class 'mesop.components.input.input.TextareaShortcutEvent'>

@me.page(path="/page2")
def page2():
    state = me.state(State)
    me.textarea(
        placeholder="Ctrl+Enter to submit",
        shortcuts={
            me.Shortcut(ctrl=True, key="Enter"): submit,
        },
    )
    me.button("submit", on_click=submit)
    me.text(state.event_type)
    # => <class 'mesop.events.events.ClickEvent'>
  1. Access /page1 and focus on the textarea and press Ctrl+Enter (works fine)
  2. Access /page2 and focus on the textarea and press Ctrl+Enter (unexpectedly triggers ClickEvent)

Expected behavior

Screenshots

When focusing on the textarea and press Ctrl+Enter:

Image

Desktop System Info

Additional context

I understand that defining separate handlers for keyboard and mouse events is the correct solution, since event types should naturally correspond to their components.

This is confusing because event types should be determined by the component (buttonClickEvent, shortcutTextareaShortcutEvent), but instead they are determined by handler registration order.

Having event types determined by registration order or handler assignment makes the behavior unpredictable and breaks the natural component-event relationship.


This happens because register_event_handler function overwrites event type mappings.

https://github.com/google/mesop/blob/69148c9ccd21346005d87b0bdac5429d136f1f65/mesop/component_helpers/helper.py#L374-L382

If it's difficult to fix this issue directly in the implementation, I would like to propose the following:

wwwillchen commented 9 hours ago

I think this is pretty difficult to fix implementation-wise and something fairly rare, please feel free to send a PR to improve the docs / add warnings. Thanks.