Sanjibukai

Sanjibukai

Experimenting with the default LiveView Dependency Search Page => Should be a better way to run Javascript Code

Hi everybody,

For those not yet aware, it’s now possible to bootstrap a Phoenix app with some liveview using the --live flag.
The default sample application seems great as a starter example.

I wanted to play around with this app and I’m still not yet convinced with the No JavaScript part.

For example, currently if I hit the search button without inputting anything yet, we are receiving a flash alert.

For example I modified this code a little so that I receive an info message and without actually running the search on the server.
Very simple modification to do in page_live.ex by adding a pattern matching with an empty query:

# live/page_live.ex
def handle_event("search", %{"q" => ""}, socket) do
  {
    :noreply,
    socket
    |> put_flash(:info, "You must provide something to search.")
  }
end

But I wanted to make the input field automatically focused.
I started by setting an id to the input field so that I can somehow target it and run the JS .focus() function on it.

# live/page_live.html.leex
<input id="search_input" type="text" name="q" value="<%= @query %>"
  placeholder="Live dependency search" list="results" autocomplete="off"/>

The following simple JS code would then do the job

document.getElementById("search_input").focus();

However I’m don’t know how to execute some bit of code within a liveview response.
But I saw that there is now some JS support using hooks.

The problem is that the hook must be set to an element we want to follow. Here since I outputting a message on the flash div, I tried to set a hook there:

# templates/layout/live.html.leex
<p class="alert alert-info" role="alert"
  phx-hook="FocusInput"
  phx-click="lv:clear-flash"
  phx-value-key="info"><%= live_flash(@flash, :info) %></p>

Then I added the following in the Javascript:

// assets/js/app.js
function focusInput() {
  document.getElementById("search_input").focus();
}

let Hooks = {}
Hooks.FocusInput = {
  updated() {
    focusInput();
  }
}
let liveSocket = new LiveSocket("/live", Socket, { params: { _csrf_token: csrfToken }, hooks: Hooks })

But it doesn’t worked.. Before trying Hooks, I tried to run some JS using an event listener on the phx:update event..
And then I said myself that maybe here the hook on updated() is not when it’s finished but before..
So I tried to put some timeout like so:

// assets/js/app.js
function focusInput() {
  setTimeout(() => { document.getElementById("search_input").focus(); }, 10)
}

And it worked! A little as 10ms did the job.
While I’m not sure why a timeout is necessary I also noticed that it worked only the first time.

The reason is because once the Flash message is displayed, and since the message itself is the same, nothing new is displayed and there is no actual update.

So I added to the flash message a timestamp like:

  |> put_flash(:info, "You must provide something to search #{DateTime.now!("Etc/UTC")}")

And now everything is working.

While I’m convinced that LiveView has huge value. I’m not sure that it could ignore JS in the client side.
There are some kind of very UI oriented things (like focusing inputs, displaying error messages, scrolling the view etc.) that I’m not sure LiveView can do by itself (I mean without running JS code).

Does anyone know how I could do this input focusing task in a better way?

I mean if possible without the timeout and without having to deal with a timestamp.
I don’t try it, but using a dedicated hidden span to receive the timestamp might work..
I’m not sure how to handle HTML within Flash message so I tried to visibility: hidden; and even display: none; on the whole Flash div. And it’s still working because the underlying HTML is still changing.

Most Liked Switch mode

chrismccord

chrismccord

Creator of Phoenix

The HTML :autofocus attribution make be enough in this case, but it varies by browser. For your hook, you should be the hook directly on the input, <input id="search" phx-hook="AutoFocus">

Hooks.AutoFocus = {
  mounted(){ this.el.focus() }
}

Last Post!

Sanjibukai

Sanjibukai

Hi Chris!
Pleasure to see you here!

The HTML :autofocus will do the job upon first display (and/or first/every mount I guess)..

However in the use case above since I don’t want to put the autofocus right away..
I could have done a bad job explaining the use case, so sorry for the confusion..

But I wanted to apply the autofocus upon a blank search.. I know that an HTML required could do the job as well but, here the main goal for me was to learn how to run some bit of JS (here autofocusing on an input, but it could have be scrolling the page).

And I think that I should set the hook on an element that is actually impacted by a life-cycle event, like an updated..

Since a flash message is displayed, I set it on the flash div..

But I’m even thinking of a dummy display: none; element that can receive (being updated with) some data (literally some text string as inner HTML).

And in that Hook I can consume that data as some command and run arbitrary JS code, which will act like a switch case..

I’m not yet onto channels and live views, but I guess that for sending (and then executing) some JS code, channel might be more suitable..

Where Next?

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2976 91332 914
New
byu
@chrismccord : I just saw the Extract AGENTS.md from Phoenix.new into phx.new generator commit to the phoenix project. My initial shotgu...
New
arcanemachine
I was working on an Ecto migration and I needed a timestamp. So, for the nth time, I looked up the different data types for timestamps, a...
New
AstonJ
Just a general thread to post chat/news/info relating to AI/ML stuff that may be relevant for Nx now or in the future. Got anything to sh...
New
type1fool
I just stumbled on a newly redesigned elixir-lang.org. :tada: It looks like @Software_Mansion did the work, and I think it is generally a...
New
juhalehtonen
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
alexslade
Fly’s CEO posted this recently - Turn And Face The Strange · The Fly Blog It says that Fly is going all-in on sprites, which is a worry ...
New

Other Trending Topics Top

jhogberg
Patch Package: OTP 28.5.0.5 Git Tag: OTP-28.5.0.5 Date: 2026-08-04 Trouble Report Id: ...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New
akoutmos
@hugobarauna and I (Alex Koutmos) have been hard at work on writing a book on Nerves that takes you from simply blinking LEDs to building...
New

We're in Beta

About us Mission Statement