Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Events such as keydown and keyup are not triggered by an ui.input when not assigned directly upon creation #4154

Open
Alyxion opened this issue Dec 30, 2024 · 1 comment
Labels
bug Something isn't working
Milestone

Comments

@Alyxion
Copy link
Contributor

Alyxion commented Dec 30, 2024

Description

During the development of a Typeahead component which attaches itself visually to the bottom of an ui.input field to (later) show search result data from a DB, i stumbled over a potential bug when modifying certain event_listeners such as keydown and keyup via the element.on method "post creation".

image

Situation:

  • An ui.input field is created
  • A focus handler is set up via .on("focus", handle_focus) and a blur_handler is setup via on("blur", handle_blur)
  • In handle_focus the.on("keydown", handle_keydown) is assigned to track cursor key presses
  • In handle_blur the event listener is removed again.
    • As NiceGUI doesn't officially support removal of event listeners added via .on yet there is a helper class involved which "cleans up again" / can unassign event listeners, but that just as side note and has no impact on this report / test as you can see in the example code attached below.
  • Expected behavior: handle_keydown will be called when a key is pressed.
  • Actual behavior: It is not

If a "keypress" or "keyup" listener is assigned later and not directly upon creation of the input field, so e.g. delayed by a timer or an event, then the handlers will never be called. If they are assigned directly upon creation, so before everything goes through the websocket from Python to JS, then they work though.

If I assign the same events directly via JavaScript to the DOM element w/ help of the new getHtmlElement function though then everything works perfectly fine. Thus there seems to be some synchronization kind of issue for certain events. A delayed assigned blur event just for example works like a charm.

from nicegui import ui

@ui.page('/')
async def index():
    log_area = ui.scroll_area().style('height: 200px; width: 400px')

    def log_key(e):
        with log_area:
            ui.label(f"Key pressed: {e.args['key']}").classes('font-mono text-xs').style('line-height: 1; margin: 0; padding: 0;')
        log_area.scroll_to(percent=1.0)

    with ui.row():
        input1 = ui.input()
        ui.run_javascript(f'''
            getHtmlElement({input1.id}).addEventListener("keydown", () => console.log("keydown on input1 via js"));
            ''')
        input1.on('keydown', log_key)   # will be triggered
        input1.on('keydown', js_handler='() => console.log("keydown on input1")')  # will be triggered
        input2 = ui.input()

    def attach_event():
        input2.on('keydown', log_key)  # will NOT be triggered
        input2.on('keydown', js_handler='() => console.log("keydown on input2")')  # will NOT be triggered
        input2.on('blur', lambda e: print('blur'))  # will be triggered
        ui.run_javascript(f'''
            getHtmlElement({input2.id}).addEventListener("keydown", () => console.log("keydown on input2 via js"));
            ''')  # will be triggered    

    # setup timer which attaches the event
    ui.timer(1.0, attach_event, once=True, immediate=False)
    
ui.run()
@falkoschindler
Copy link
Contributor

Interesting observation, @Alyxion!

This handler does not work:

i = ui.input()
ui.timer(1.0, lambda: i.on('keydown', ui.notify), once=True)

But button click handlers can be assigned this way. So it's not a general event registration problem.

b = ui.button()
ui.timer(1.0, lambda: b.on('click', ui.notify), once=True)

And as far as I can tell, the event listeners are registered correctly and sent to the client. But there is no websocket message sent to the server when a key is pressed. Very strange!

@falkoschindler falkoschindler added the bug Something isn't working label Jan 7, 2025
@falkoschindler falkoschindler added this to the 2.10 milestone Jan 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants