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

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() }
}

Where Next?

Popular in Discussions Top

blackode
Elixir Upgrading is so Simple in Ubuntu and It worked for me Ubuntu 16.04 git clone https://github.com/elixir-lang/elixir.git cd elixir...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New
CharlesO
Erlang :list.nth simple, but 1 - based nth(1, [H|_]) -&gt; H; nth(N, [_|T]) when N &gt; 1 -&gt; nth(N - 1, T). Elixir Enum.at … coo...
New
ejpcmac
I have discovered Nix last month and I am currently on my way to migrating to it—both on macOS at home and the full NixOS distrubution at...
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31142 143
New
marciol
Please, let me know if this kind of discussion already took place in another topic . Hi all, how do you consider if is better to build ...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
und0ck3d
Hello everyone! A few days ago I’ve created a topic here about how people were creating CMSs with Elixir and Phoenix. I’ve been studying...
New
RudManusachi
What configs will make sense to put to runtime.exs? – A bit of how I configure apps: I have generic configs in config/config.exs, dev...
New

Other popular topics Top

danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29377 241
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43622 214
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 53690 245
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New

We're in Beta

About us Mission Statement