pillaiindu

pillaiindu

What's wrong with my Phoenix LiveView code?

Currently reading the book “Programming Phoenix LiveView”.
At the end of the Chapter 1, I’m trying to solve the guess game. If the user guesses the random number generated by the program the program should say Your guess: #{guess}. Correct!, but it doesn’t run that condition even if the guessed number is exactly the same as the random_number generated at the time of mount.
I’ve also added the line The randome number is <%= @random %> to see if I’m guessing the correct number.

Following is the code.

defmodule PentoWeb.WrongLive do
  use PentoWeb, :live_view

  def mount(_params, _session, socket) do
    {:ok, assign(socket, score: 0, message: "Make a guess:", time: time(), random: random())}
  end

  def render(assigns) do
    ~H"""
    <h1 class="mb-4 text-4xl font-extrabold">Your score: <%= @score %></h1>
    <h2>
      <%= @message %>
      The randome number is <%= @random %>
    </h2>
    <br/>
    <h2>
      <%= for n <- 1..10 do %>
        <.link class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 border border-blue-700 rounded m-1" phx-click="guess" phx-value-number= {n} >
          <%= n %>
        </.link>
      <% end %>
    </h2>
    """
  end

  def time() do
    DateTime.utc_now() |> to_string()
  end

  def random() do
    Enum.random(1..10)
  end

  def handle_event("guess", %{"number" => guess}, socket) do
    message = cond do
      guess == socket.assigns.random ->
        "Your guess: #{guess}. Correct!"
      true ->
        "Your guess: #{guess}. Wrong. Guess again."
    end

    {:noreply, assign(socket, score: socket.assigns.score + 1, message: message, time: time(), random: socket.assigns.random)}
  end
end

@SophieDeBenedetto

Most Liked

zimt28

zimt28

Your guess variable in the handle_event function is a string, so guess == socket.assigns.random is comparing a string against an integer. An easy fix would be to return a string from your random/0 function.

pillaiindu

pillaiindu

Bard said to make the handle_event like this,

  def handle_event("guess", %{"number" => guess}, socket) do
    message = cond do
      guess == socket.assigns.random ->
        "Your guess: #{guess}. Correct!"
        {:noreply, assign(socket, random: random())}
      true ->
        "Your guess: #{guess}. Wrong. Guess again."
    end

      {:noreply, assign(socket, score: socket.assigns.score + 1, message: message, time: time())}
    end

but that didn’t work either.

pillaiindu

pillaiindu

Thank you for your reply!

It doesn’t work. I tried converting the value inside random() function to String, it didn’t work that way.
Then I converted the guess coming from the user inside the handle_event to integer before comparing it with socket.assign.random, it didn’t work again.

Right now my code is as follows,

defmodule PentoWeb.WrongLive do
  use PentoWeb, :live_view

  def mount(_params, _session, socket) do
    {:ok, assign(socket, score: 0, message: "Make a guess:", time: time(), random: random())}
  end

  def render(assigns) do
    ~H"""
    <h1 class="mb-4 text-4xl font-extrabold">Your score: <%= @score %></h1>
    <h2>
      <%= @message %>
      The randome number is <%= @random %>
    </h2>
    <br/>
    <h2>
      <%= for n <- 1..10 do %>
        <.link class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 border border-blue-700 rounded m-1" phx-click="guess" phx-value-number= {n} >
          <%= n %>
        </.link>
      <% end %>
    </h2>
    """
  end

  def time() do
    DateTime.utc_now()
  end

  def random() do
    Enum.random(1..10)
  end

  def handle_event("guess", %{"number" => guess}, socket) do
    guess = Integer.parse(guess) |> elem(0)
    message = cond do
      guess == socket.assigns.random ->
        "Your guess: #{guess}. Correct!"
        {:noreply, assign(socket, random: random())}
      true ->
        "Your guess: #{guess}. Wrong. Guess again."
    end

      {:noreply, assign(socket, score: socket.assigns.score + 1, message: message, time: time())}
    end
  end

At this point when I click the correct option, it gives the following error,

[debug] HANDLE EVENT "guess" in PentoWeb.WrongLive
  Parameters: %{"number" => "3"}
[debug] Replied in 729µs
[error] GenServer #PID<0.505.0> terminating
** (Protocol.UndefinedError) protocol Phoenix.HTML.Safe not implemented for {:noreply, #Phoenix.LiveView.Socket<id: "phx-F5RYrXnIuZbLRwBE", endpoint: PentoWeb.Endpoint, view: PentoWeb.WrongLive, parent_pid: nil, root_pid: #PID<0.505.0>, router: PentoWeb.Router, assigns: %{message: "Make a guess:", time: ~U[2023-11-04 06:49:57.476986Z], random: 2, __changed__: %{random: true}, flash: %{}, live_action: nil, score: 0}, transport_pid: #PID<0.497.0>, ...>} of type Tuple. This protocol is implemented for the following type(s): Atom, BitString, Date, DateTime, Decimal, Float, Integer, List, NaiveDateTime, Phoenix.HTML.Form, Phoenix.LiveComponent.CID, Phoenix.LiveView.Component, Phoenix.LiveView.Comprehension, Phoenix.LiveView.JS, Phoenix.LiveView.Rendered, Time, Tuple, URI
    (phoenix_html 3.3.3) lib/phoenix_html/safe.ex:97: Phoenix.HTML.Safe.Tuple.to_iodata/1
    (pento 0.1.0) lib/pento_web/live/wrong_live.ex:12: anonymous fn/2 in PentoWeb.WrongLive.render/1
    (phoenix_live_view 0.19.5) lib/phoenix_live_view/diff.ex:363: Phoenix.LiveView.Diff.traverse/7
    (phoenix_live_view 0.19.5) lib/phoenix_live_view/diff.ex:538: anonymous fn/4 in Phoenix.LiveView.Diff.traverse_dynamic/7
    (elixir 1.15.7) lib/enum.ex:2510: Enum."-reduce/3-lists^foldl/2-0-"/3
    (phoenix_live_view 0.19.5) lib/phoenix_live_view/diff.ex:361: Phoenix.LiveView.Diff.traverse/7
    (phoenix_live_view 0.19.5) lib/phoenix_live_view/diff.ex:136: Phoenix.LiveView.Diff.render/3
    (phoenix_live_view 0.19.5) lib/phoenix_live_view/channel.ex:833: Phoenix.LiveView.Channel.render_diff/3
    (phoenix_live_view 0.19.5) lib/phoenix_live_view/channel.ex:689: Phoenix.LiveView.Channel.handle_changed/4
    (stdlib 5.1.1) gen_server.erl:1077: :gen_server.try_handle_info/3
    (stdlib 5.1.1) gen_server.erl:1165: :gen_server.handle_msg/6
    (stdlib 5.1.1) proc_lib.erl:251: :proc_lib.wake_up/3
Last message: %Phoenix.Socket.Message{topic: "lv:phx-F5RYrXnIuZbLRwBE", event: "event", payload: %{"event" => "guess", "type" => "click", "value" => %{"number" => "3"}}, ref: "13", join_ref: "11"}
State: %{socket: #Phoenix.LiveView.Socket<id: "phx-F5RYrXnIuZbLRwBE", endpoint: PentoWeb.Endpoint, view: PentoWeb.WrongLive, parent_pid: nil, root_pid: #PID<0.505.0>, router: PentoWeb.Router, assigns: %{message: "Make a guess:", time: ~U[2023-11-04 06:49:57.476986Z], random: 3, __changed__: %{}, flash: %{}, live_action: nil, score: 0}, transport_pid: #PID<0.497.0>, ...>, components: {%{}, %{}, 1}, topic: "lv:phx-F5RYrXnIuZbLRwBE", serializer: Phoenix.Socket.V2.JSONSerializer, join_ref: "11", upload_names: %{}, upload_pids: %{}}
[debug] MOUNT PentoWeb.WrongLive
  Parameters: %{}
  Session: %{"_csrf_token" => "-UTX1GiHNYDm90jd4qqktPfh"}
[debug] Replied in 104µs

Where Next?

Popular Backend topics Top

andrea
Can Phoenix LiveView be used in multi-page applications, unlike React/Vue/Blazor which seems to be targeted for SPA?
New
New
mrmurphy
I’ve run into a situation where I’ve got a list of posts inside of a container that uses phx-update=“prepend”, and the posts on the socke...
New
sampu
I have a use case where a client is invoking a Rest endpoint via a load balancer, which in turn invokes a third party endpoint which is r...
New
Fl4m3Ph03n1x
Background I am now trying Gradual type checking, as a consequence I am giving a shot to Gradient. As I see it, this is an alternative to...
New
Fl4m3Ph03n1x
Background I am trying to find a cheap and easy way to create New Types in Elixir, and Records seem to be just what I would need. Probl...
New
AstonJ
If when trying to create (or recreate) your dev db with rails db:create you are getting: PG::ConnectionBad: connection to server on soc...
New
Fl4m3Ph03n1x
Background I am a fan of dialyzer and friends (looking at Gradient) and I try to have sepcs in my code as much as I can. To this end, I a...
New
Fl4m3Ph03n1x
Background I have an umbrella app where I use a dependecy called ETS. This dependency has a type called set_options that I use in some of...
New
yamuna
Hi everyone, I’m trying to run deepseek-coder:6.7b-instruct-q4_K_M in Docker using Ollama to create an LLM that will be used by CrewAI a...
New

Other popular topics Top

Devtalk
Hello Devtalk World! Please let us know a little about who you are and where you’re from :nerd_face:
New
PragmaticBookshelf
Design and develop sophisticated 2D games that are as much fun to make as they are to play. From particle effects and pathfinding to soci...
New
AstonJ
This looks like a stunning keycap set :orange_heart: A LEGENDARY KEYBOARD LIVES ON When you bought an Apple Macintosh computer in the e...
New
AstonJ
Do the test and post your score :nerd_face: :keyboard: If possible, please add info such as the keyboard you’re using, the layout (Qw...
New
New
AstonJ
If you want a quick and easy way to block any website on your Mac using Little Snitch simply… File &gt; New Rule: And select Deny, O...
New
husaindevelop
Inside our android webview app, we are trying to paste the copied content from another app eg (notes) using navigator.clipboard.readtext ...
New
New
PragmaticBookshelf
Develop, deploy, and debug BEAM applications using BEAMOps: a new paradigm that focuses on scalability, fault tolerance, and owning each ...
New
PragmaticBookshelf
Get the comprehensive, insider information you need for Rails 8 with the new edition of this award-winning classic. Sam Ruby @rubys ...
New