scan history table from db with pubsub: statistics, colors, time,…
When the hardware scanner is used and a scan is made, a sequence of characters is send ending with an Enter-key.
defmodule HelloWeb.ScanLive do
use HelloWeb, :live_view
def render(assigns) do
~H"""
<div phx-window-keyup="scanner">
</div>
"""
end
def handle_event("scanner", key, socket) do
IO.inspect(key)
{:noreply, socket}
end
end
Is this the proper way to do this in Phoenix Liveview using handle_event with keyup?
Can you capture a sequence+Enter at once or do you have to capture separately and build it up.
If you want to capture each key individually, yes.
This requires a form input. I am curious why specifically you wish to avoid this. I can give you a working example (using an ancient Symbol LS1900 barcode scanner to demonstrate ):
Here’s the code:
defmodule HelloWeb.ScanLive do
use HelloWeb, :live_view
def render(assigns) do
~H"""
<form id="form" phx-submit={JS.push("capture") |> JS.push_focus(to: "#input")}>
<input
id="input"
data-count={@count}
type="text"
name="code"
autofocus
phx-debounce="blur"
placeholder="Scan barcode..."
value=""
class="w-full"
/>
<button class="hidden" type="submit">Submit</button>
</form>
<ul>
<li :for={code <- @codes}><%= code %></li>
</ul>
"""
end
def mount(_, _, socket) do
socket = socket |> assign(:count, 0) |> assign(:codes, [])
{:ok, socket}
end
def handle_event("capture", %{"code" => code}, socket) do
IO.inspect(code)
socket =
socket
|> update(:count, &(&1 + 1))
|> update(:codes, &[code | &1])
{:noreply, socket}
end
end
Usually there are (at least) two tricky parts. The first is clearing and re-focusing the input after the form submits. You can use a combination of JS.push() and JS.push_focus() to submit the form and re-focus the input. To ensure the input is cleared after submit, you need to force the input to re-render. In this case I am setting a data-count attribute and incrementing the count on each submit. This will force LiveView to re-render the input with the empty value provided on the element.
The other tricky part is that barcode scanners don’t always send an Enter key as a suffix. I left the phx-debounce="blur" on the input because you will definitely want that if you try to add a phx-change event to the form. Since LiveView won’t re-render focused inputs on change, you would probably want to push an event from the server and use it to reset the input value.
Thank you. I’ve tried similar with a form & changeset & onfocus: "this.value=''"'to reset the value. Your code is much cleaner though.
I have currently 2 reasons. I’m testing with an android phone with 2d scanner (Blovedream U9000)
When the focus is on the input the software keyboard keeps popping up. I though when there is no input, there would be no software keyboard filling half the screen. Edit: Adding inputmode="none" to input fixes this.
When the user clicks outside the input, the focus is lost. Scans are not captured until you refocus on the input.
For capturing a sequence+Enter at once, I’m not sure if that’s possible. It might be easier to capture the sequence and then add the Enter key as a separate event.
Regarding your issue with the software keyboard popping up, adding inputmode=“none” to the input should fix that.