r4z4
Request: LiveView Timer Example
Hello
I am struggling to implement a simple timer in LiveView, and so I was wondering if anyone knew of any good examples out there that I could take a look at? I just want to display a simple countdown timer on the page, and have access to those values (the count). Thanks ![]()
Marked As Solved
zachallaun
This is a LiveComponent, not a LiveView, which means its rendered “embedded” is another process – not as its own process. If you stick a handle_info in the module that renders this, does a message come through?
Also Liked
zachallaun
Awesome!
I’d recommend this section of the docs. Also, at the risk of going too far, I think you’re doing yourself a disservice by using Surface while you’re getting started with and familiar with LiveView. I think Surface is awesome, but especially with LiveView 0.18+, much of the gap has been closed, and it will be much easier to find solutions/understand what’s going on if you don’t have to look in two places.
For instance, I think the Surface automatically delegates handle_event to live components, e.g.
# When using Surface
use Surface.LiveComponent
def render(assigns) do
~F"""
<button :on-click="some_event">Button</button>
"""
end
def handle_event("some_event", _, socket) do
...
end
# When using LiveView
use Phoenix.LiveComponent
def render(assigns) do
~H"""
<button phx-click="some_event" phx-target={@myself}>Button</button>
"""
end
def handle_event("some_event", _, socket) do
...
end
Notice that in the Phoenix.LiveComponent version, you have to explicitly target @myself for the event to go to the live component and not the parent live view. I believe Surface does that delegation automatically, but it obviously can’t delegate send(self(), ...) because it doesn’t have that level of control.
samc
I’m not sure about other examples out there but here is how I would approach just a simple countdown using erlang’s :timer
defmodule MyAppWeb.ExampleLive do
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
if connected?(socket), do: :timer.send_interval(1000, self(), :tick)
{:ok, assign(socket, %{count: 60})}
end
def handle_info(:tick, socket) do
{:noreply, assign(socket, count: socket.assigns.count - 1)}
end
def render(assigns) do
~H"""
<div><%= @count %></div>
"""
end
end
Calling :timer.send_interval will send a message to the liveview process (i.e. itself) that can then be handled to decrement the current count. The count variable will be available in socket.assigns.count to use elsewhere or to add some logic when the timer reaches zero etc.
Sebb
this minimal example works for me, ie getting these warnings of unhandled msgs and responding to GET with “test”.
debug] warning: undefined handle_info in ToolPocWeb.ToolLive. Unhandled message: :tick
defmodule TestWeb.TestLive do
use TestWeb, :live_view
def mount(_, _, socket) do
if connected?(socket), do: :timer.send_interval(1000, self(), :tick)
{:ok, socket}
end
def render(assigns) do
~H"""
test
"""
end
end








