Phx-key attribute doubt

Any docs on the phx-key , key event?

the docs only contain phx-window-onkeyup/down. So idk the diff between phx-onkeyup & phx-window-onkeyup, nor do I know what phx-key is or how to use it

I have an event handler that needs to trigger only when a specific key is pressed, so was looking into it

The LiveView documentation for Key Events should hopefully answer your questions.

In short:

  • phx-* is used to provide a element-level binding, aka. trigger events when pressing keys on a specific HTML element
  • phx-window-* is used to provide a window-level binding, aka. trigger events when pressing keys anywhere on the web page
  • phx-key is an optional attribute used to limit triggering of the event to just the key provided in the attribute (instead of triggering the event for any key-press)
1 Like

thanks your last line helps ig. I was trying phx-key=“Shift” but it wasnt working. Ig it works with onkeyup/down together

ive tried this-

    <.form for={@form} phx-submit="submit" phx-keydown="key_handler" phx-key="Shift">
  def handle_event("key_handler", idk, socket) do "working"
  	{:noreply, socket}

But it doesnt log anything if im using phx-keydown in the textarea field within this form. But if I use phx-window-keydown it does work. ?

My hypothesis would be that, if you are focusing on an input child element of the <.form>, the key press event would not bubble up to the parent in which your phx- binding is placed. This would explain why you’re able to see something with phx-window but not otherwise (i.e. there’s definitely a Shift key press event happening somewhere, but not on the DOM element where you’re trying to capture it.).

yes that it a good explanation. So what do I do? how to enable bubbling?

Hmm, so the keydown doesn’t work for me (nor keyup) even without the phx-key up at the form level, even using just a standard <form> - whereas click works as expected. Might be a bug.

FWIW, the bubbling certainly does work when you attach regular keydown/up events using JS.

so do I open up a PR?

@chrismccord are we missing something here?

Thanks for testing it out. I looked a little more into the code this morning. The MDN docs state that:

Keyboard events are only generated by <input> , <textarea> , <summary> and anything with the contentEditable or tabindex attribute. If not caught, they bubble up the DOM tree until they reach Document.

However, the bind function defined in looks at the for the presence of the phx-* binding, otherwise propagating up to any phx-window-* bindings. In this case, we want the <.form> to have the eventListener, but the target is the <input> element and not the <form>, so it doesn’t trigger anything.

The bindForms() function handles several eventListeners, but key presses are not one of those events. It seems reasonable that this function could attach eventListeners for that subset of events where it’s known that is not the element itself but is necessarily a child of the element having the phx-* attribute.

(edit: since library changes take time, and @chrismccord might have good reasons to not want to fiddle with the event propagation beyond the current capabilities, I thought I’d offer some work arounds)

  1. Individually add the key down/up/press binding to each input field within the form. This should trigger the event, but I don’t know if it might be more difficult to traverse back to an identifiable parent on the server side event handling depending on what you’re ultimately trying to do in your handle_event callback.
  2. Use a Hook to add the event listener to the form instead, which can then use pushEvent to push an event over the socket without relying the phx-keydown binding. I think it would be pretty small piece of JS code, and the docs at JavaScript interoperability — Phoenix LiveView v0.19.5 are probably sufficient to get you running.

I’d lean towards #2 if I were doing it.

Ah, and (not looking closely) it looks like click is handled differently.