r4z4

r4z4

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 :slight_smile:

Showing Posts 1 to 10

w0rd-driven

w0rd-driven

The dockyard academy curriculum has a counter example in liveview as well as a normal view version in an earlier reading. curriculum/reading/liveview.livemd at main · DockYard-Academy/curriculum · GitHub.

In the example there’s a count and you can press a button to increment or use the input field to specify how much to increment by.

samc

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.

r4z4

r4z4 OP

Hey @samc thanks for the reply

I guess this is why this is driving me so crazy. I love how simple it is, right. But … it doesn’t work. I cannot for the life of me get handle_info to receive anything. I remember reading it was only for a GenServer, and then recently read that it was not, but I am starting to think maybe the original (probably one randomly stumbled-upon) item I read might have been right?

I’m just kind of at a loss for words. A few of the random thoughts I have had were: 1. Is it an issue with the self() → Are we able to send to a LiveView, in that, is it a “Process” we can send it to. I know it is a process, but is it? (I hope you know what I mean there and I say that partly in jest). 2. Is is the message format but I have tried non-atoms and all other sorts and nothing seems to give.

Here is my cleaned up version of what I am working with now. I can gladly show you all the other iterations I have tried as I have pretty much thrown the kitchen sink at this thing.

I really appreciate people taking the time to have a look and offer some assistance though … it really help :slight_smile:

defmodule SurfaceAppWeb.Components.Timer do
  use Surface.LiveComponent

  data seconds, :integer

  def mount(socket) do
    if connected?(socket), do: :timer.send_interval(1000, self(), :tick)

    {:ok, socket |> assign(seconds: 15)}
  end

  def render(assigns) do
    ~F"""
    <div>
      <h2>{ @seconds }</h2>
    </div>
    """
  end

  def handle_info(:tick, socket) do
    IO.puts "hey"
    {:noreply, assign(socket, seconds: socket.assigns.seconds - 1)}
  end

end
r4z4

r4z4 OP

Thanks for the link. I cannot say I am all that familiar with DockYard Academy but it looks promising. I think I saw some similar examples and they were helpful, but I am looking for the automated counter example. Part of the reason why it is so frustrating is how difficult it is compared to these examples though where user action signifies the event. Just need to bridge that gap.

Thank you though, I appreciate the help!!

sergio

sergio

A liveview is kind of like a genserver underneath, right @chrismccord? I think I read or heard you saying that somewhere.

Anyway, make sure that your socket is connecting maybe that’s why you’re not getting it to work.

My brother on Brave Browser sometimes has this weird bug where the blue phx loading thing hangs for a long time and then it resolves itself and the socket connects normally after that. Do you see the blue loading bar at the top of the screen loading infinitely?

r4z4

r4z4 OP

Hey @sergio

Your brother is definitely correct and Brave sockets behave strangely, but unfortunately I get the same issues in Chrome and Edge. I will do some more verifying on the connection but seems that all other aspects of the app work, just that handle_info call.

Sebb

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
w0rd-driven

w0rd-driven

Sorry I didn’t read the topic of timer vs counter. The timer example is at curriculum/exercises/timer.livemd at main · DockYard-Academy/curriculum · GitHub.

I think the academy curriculum is a good companion to exercism.io. I had the privilege of going through a beta cohort and being compelled to work through the materials 5-6 days a week helped solidify concepts I wasn’t grokking. Exercism’s syllabus is a great way of gating complex topics behind fundamentals but I think analysis paralysis made it hard for me to stick with it. The academy curriculum also covers topics outside of language fundamentals.

LiveViews are a genserver under the hood so what you have should work according to the proposed solutions. I prefer Process.send_after personally but you have to call it every time you process the message. handle_info is used to capture messages you pass from inside or outside the current process. From the Surface and LiveView docs it’s possible you may need to use Phoenix.LiveView — Phoenix LiveView v1.2.5. That isn’t supposed to be a concern for just a genserver but liveviews and their components take a little extra work to synchronize the state between processes.

zachallaun

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?

r4z4

r4z4 OP

Ah, @zachallaun I think that will do it. I am able to get the handle_info on the LiveView, so I think I just need to do some restructuring a little bit. Woof. Thank you so much, that was really driving me crazy. Of course I am sure the info was probably right there in front of me at some point - gotta work on that I suppose :slight_smile:

Thanks again, I really appreciate the help from everyone. I am off to read more on LiveComponents

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
apz
I’m new to elixir and just tried to install the elixirLS extension for VScode(ium) and it is throwing some errors that I would like help ...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
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
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
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

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews