Programming Phoenix LiveView: P27, live_path confusion

I am working on the “Your Turn” for chapter one and building out the restart button talked about on page 27. It recommends looking into the live_patch function to patch the view and add the button. Many examples involving live_patch I found on the web suggested something like

<%= live_patch to: Routes.live_path(@socket, __MODULE__), replace: true do %>
   <button>Try again!</button>
<%end>

but Elixir complains with

warning: Routes.live_path/2 is undefined (module Routes is not available or is yet to be defined)
  lib/pento_web/live/wrong_live.ex:50: PentoWeb.WrongLive.render/1

mix phx.routes says the helper is defined:

$ mix phx.routes
          page_path  GET  /                                      Phoenix.LiveView.Plug :index
          live_path  GET  /guess                                 Phoenix.LiveView.Plug PentoWeb.WrongLive
live_dashboard_path  GET  /dashboard                             Phoenix.LiveView.Plug :home
live_dashboard_path  GET  /dashboard/:page                       Phoenix.LiveView.Plug :page
live_dashboard_path  GET  /dashboard/:node/:page                 Phoenix.LiveView.Plug :page
          websocket  WS   /live/websocket                        Phoenix.LiveView.Socket
           longpoll  GET  /live/longpoll                         Phoenix.LiveView.Socket
           longpoll  POST  /live/longpoll                         Phoenix.LiveView.Socket
          websocket  WS   /socket/websocket                      PentoWeb.UserSocket

So I must be missing a use or alias somewhere? Help?

2 Likes

Hey @cro! What you have here looks 100% right to me (except you are missing the % before the closing tag in the <% end>, but that would be throwing a different error entirely). Where is it that you are adding this code snippet in your code? Also feel free to push up your code to a repo and share it with me if you’d like. I’d be happy to take a closer look!

Re-posting here for visibility bc I accidentally replied privately:

Mystery solved!

At the top of your PentoWeb.WrongLive module, you should pull in the LiveView behavior like this:

defmodule PentoWeb.WrongLive do
  use PentoWeb, :live_view

I think there was someplace in the book where we gave you an outdated instruction to do so like this instead:

defmodule PentoWeb.WrongLive do
  use Phoenix.LiveView

That has since been corrected but I’m not sure if the fix is out in the Beta release from last week or if it will be included in the next one. In either case, that is the change you need to make and I’m sorry for any confusion this caused!

Let me know if this un-sticks you or if you encounter any other errors :slight_smile:
And @cro confirmed this fixed the issue!

Thank you, thank you thank you for bringing this up. I love elixir and all the people pushing the technology forward. It’s one of the greatest technologies since sliced bread… but I felt really stranded with this - Throw me off the side of the cliff and see if I can find my parachute.

I was excitedly looking forward to completing the exercise - so I hurriedly clicked the link to learn about this “live_patch” business. And boy - did I find that I had NO idea how to use what it was talking about. The LiveView help was not helpful for people learning LiveView - but only for those that already know LiveView and need a reminder.

I was disappointed “Sophie or Bruce” that you sent me to the den of Lions. You could have at least ended the link with a “Buwahahaha Buhahaha” as a warning that I was going to run into a steel wall at 100 miles an hour.

Then I search the internet - looking for an example. Because I knew that Bruce-or-Sophie was going to say - well, did you Google it (Google is everyone’s escape hatch) - I didn’t want to be on the wrong side - so I made sure that I went to as many places that Google sent me.

NOTHING - there were a few places with lip-service on the topic of live_patch.

I finally come across a discussion where José Valim gives a little bit better explanation of what live_patch does in comparison to it’s sibling alternative functions such as live_redirect, live_push etc.

But, still - NO examples of how a button or even a simple link plays a role in restarting a simple “You’re wrong” game.

Frustrated ?? - well … not overly - I still have sympathy for people that make hard things.

So, after going thru all those links starting from the book - I still don’t even know “What” get’s patched with “what.”

The instructions said - make a button to restart the game. We have barely even displayed our first screen - and now I’m asked to chase down ghost instructions.

C’mon Sophie and Bruce - Show some love. :slight_smile:

What’s the answer?

Yours Truly
Grumpy ol’ man

P.S.

“Shame on me.” I thought. I had surely forgotten to look at the source code that came with the book. I didn’t think of this until I wrote my long manifesto above.

I downloaded the code - opened the whole glob in Visual Studio - and searched the whole thing for “live_patch”

There were several hits. However, - none related directly to the resetting the game. I peeked at the other implementations - of course they didn’t make sense to me because I don’t have enough context to which they apply.

So, I would like to make a recommendation to the authors.

I know it’s hard writing a book and a good one. But, it would be extremely helpful to the learner - if you would put the solutions in your code.

OR

at least state - “We are going to cover this topic thoroughly in a later chapter. We promise not to leave you hanging.”

Ok, back to irritating my wife with the “The Little Elixir & OTP Guidebook” audio book.

Hi @IwateKyle, I’m sorry to hear that you found this particular exercise so challenging. Rest assured that live_patch is covered in greater detailed later on in the book and we will update the text to let readers know.

In the meantime, here is some guidance on the solution:

  • Per the docs here (and as shown in the original question on this thread above), you can write the live_patch function call in the markup in the render function of WrongLive like this:
<%= live_patch to: Routes.live_path(@socket, __MODULE__), replace: true do %>
      <button>Try again!</button>
<%end%>

This adds a button that is wrapped in a special kind of link called a “live patch”. A “live patch” link basically re-directs to the current live view without reloading it. From the docs, if you call live_patch with the route to the current live view…

…the new state is pushed to the client, without reloading the whole page while also maintaining the current scroll position

The value of the :to key in the argument to live_patch can be any route. To specify the route of the current live view, you use: Routes.live_path(@socket, __MODULE__) or you could use Routes.live_path(@socket, PentoWeb.WrongLive), which evaluates to the same thing. The third example in the docs here is accurate Phoenix.LiveView.Helpers — Phoenix LiveView v0.15.7.

To fully get this working, you need to add this live_patch link I described above, and you need to implement a new function in your live view, a handle_params/3 function. From the docs:

When navigating to the current LiveView, Phoenix.LiveView.handle_params/3 is immediately invoked to handle the change of params and URL state.

If you follow the link to the handle_params/3 docs, you will see that it takes in three arguments: some params, the URI and the socket, and it needs to return {:noreply, socket}. If we are aiming to “reset” the game, then we should return a socket with the appropriate starting state. So something like this:

def handle_params(_params, _uri, socket) do
    {
      :noreply,
      assign(
        socket,
        score: 0,
        message: "Guess a number."
      )
    }
  end

That should do it! I hope this helps and thanks very much for your feedback.

Bless you Sophie. You are a super star! I appreciate your time. I’ve since moved ahead, but I’ll definitely add this to exercise. :slight_smile:

1 Like