LiveView - simple counter app is not working

I’m sure I am doing something wrong but I cannot figure out what bit is missing.

I followed official LiveView installation process and the simple counter application is displaying fine.
However the buttons +/- do not do anything, like the event isn’t being fired. Also, when tried to enable
debugging in the browser console, I get Uncaught ReferenceError: liveSocket is not defined which
indicates the socket is not present.

Could use some pointers here.

https://dpaste.org/eXbg

# router.ex
pipeline :browser do
...
+ plug :put_root_layout, {HiveWeb.LayoutView, :app}
end
# app.html.eex
- <%= render @view_module, @view_template, assigns %>
+ @inner_content

The problem is that you aren’t loading app.js (check the rendered html source). Now you need to specifically set the root layout.

2 Likes

This seems to solve my issue. Thank you.

I must say starting out isn’t as straight forward as following the official docs.

3 Likes

Quick question tho.

Why am I getting this error
assign @inner_content not available in eex template.
when I navigate back to “/”. I’m sure it’s caused by put_root_layout but now
I’m not sure how should I structure it.
Some more reading is definitely required.

Have a look at the Live Layouts part of the docs.

There are some variations that you can explore and it depends how similar your layouts are between the live view and what is not live view. One alternative is to have 2 layouts, one called root.html.eex that will contain basically what the common app layout use to have (HTML head, header, footer and so on), the only difference is that it will load the inner templates with <%= @inner_content %>. Then you will have a second layout called app.html.eex that will be used to render all non-LiveView elements, this layout is minimal and can contain simply <%= render @view_module, @view_template, assigns %>.

As I mentioned, depending how different your layouts for LiveView are compared with non-LiveView you can even have a specific layout called live_view.leex and have specific pipeline in the router to use that layout for LiveView pages.

Thank you. Have been playing a little bit in my spare time now. Still struggling though and
most materials are out of date as LiveView’s developing rapidly.
What I’m looking to achieve is I’d say standard template structure:

<navigation>
<live content>
<footer>

I know it’s silly for anyone experienced with phoenix but got to start somewhere.

Adam, this should be enough for the basic. In your router you will set the root layout, and you will define the root template that will contain everything around with the placement for live view templates and non-live view templates:

/lib/web/router.ex

# code
  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_live_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
    plug :put_root_layout, {Web.LayoutView, :root}
  end
# code

/lib/web/templates/layout/root.html.eex

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Title</title>
    <link rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
  </head>
  <body>
    <nav></nav>
    <%= @inner_content %>
    <footer></footer> 
    <%= csrf_meta_tag() %>
    <script type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
  </body>
</html>

/lib/web/templates/layout/app.html.eex

<%= render @view_module, @view_template, assigns %>
4 Likes

Awesome. Really appreciate it.