I was following this guide:
https://hexdocs.pm/phoenix_live_view/installation.html
To add LiveView support to an existing Phoenix app. I found I was getting a compilation error:
== Compilation error in file lib/app_web/live/example_live/show.ex ==
** (UndefinedFunctionError) function AppWeb.live_view/0 is undefined or private
AppWeb.live_view()
expanding macro: AppWeb.__using__/1
lib/app_web/live/example_live/show.ex:2: AppWeb.ExampleLive.Show (module)
(elixir) expanding macro: Kernel.use/2
lib/app_web/live/example_live/show.ex:2: AppWeb.ExampleLive.Show (module)
(elixir) lib/kernel/parallel_compiler.ex:229: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7
Looking at the generated template file here:
It looks like the instructions to add some lines to lib/my_app_web.ex are incomplete - I also needed to add the live_view and live_component functions. I also found I needed to add:
import Phoenix.LiveView.Helpers
import CloeWeb.LiveHelpers
into live_view/0. (not sure if that is correct as I'm new to Phoenix but it fixed the next errors I got).
Looks like you typo'd a step. Did you include use AppWeb.Example.live_view by accident instead of use AppWeb, :live_view ? Failing that, can you share your show.ex module? Thanks!
_Note: I replaced Cloe => App and Room => Example in my issue report above. I've gone back to the real app names below to avoid confusion._
Nope, show.ex had use CloeWeb, :live_view in it as the first line - that was part of the generated code, I didn't write it.
I should mention that I ran:
mix phx.gen.live Rooms Room rooms --no-context --no-schema
Because I was trying to add a new LiveView route to an existing context.
Here's the full show.ex:
defmodule CloeWeb.RoomLive.Show do
use CloeWeb, :live_view
alias Cloe.Rooms
@impl true
def mount(_params, _session, socket) do
{:ok, socket}
end
@impl true
def handle_params(%{"id" => id}, _, socket) do
{:noreply,
socket
|> assign(:page_title, page_title(socket.assigns.live_action))
|> assign(:room, Rooms.get_room!(id))}
end
defp page_title(:show), do: "Show Room"
defp page_title(:edit), do: "Edit Room"
end
and the original error (without edits):
Erlang/OTP 22 [erts-10.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]
Compiling 23 files (.ex)
== Compilation error in file lib/cloe_web/live/room_live/show.ex ==
** (UndefinedFunctionError) function CloeWeb.room_view/0 is undefined or private
CloeWeb.room_view()
expanding macro: CloeWeb.__using__/1
lib/cloe_web/live/room_live/show.ex:2: CloeWeb.RoomLive.Show (module)
(elixir) expanding macro: Kernel.use/2
lib/cloe_web/live/room_live/show.ex:2: CloeWeb.RoomLive.Show (module)
(elixir) lib/kernel/parallel_compiler.ex:229: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7
Can you include your entire project, or at least your app_web.ex? The 2nd stacktrace you posted is different than the first. This one is showing CloeWeb.room_view/0 is undefined or private
CloeWeb.room_view() where the other one was live_view/0 is undefined. You indeed need to add the live_view/0 clause to your app_web.ex, and the generator should have output:
https://github.com/phoenixframework/phoenix/blob/master/lib/mix/tasks/phx.gen.live.ex#L181-L183
Sorry, I was trying a bunch of things to fix it and looks like I pulled the wrong error out of my console history. The error was definitely about live_view/0.
That output from the generator is the hint I was missing, but I saved the output from running mix phx.gen.live and it doesn't look like it showed for me for some reason (could it be because I ran with --no-context --no-schema?). This was the output I got:
* creating lib/cloe_web/live/room_live/show.ex
* creating lib/cloe_web/live/room_live/index.ex
* creating lib/cloe_web/live/room_live/form_component.ex
* creating lib/cloe_web/live/room_live/form_component.html.leex
* creating lib/cloe_web/live/room_live/index.html.leex
* creating lib/cloe_web/live/room_live/show.html.leex
* creating test/cloe_web/live/room_live_test.exs
* creating lib/cloe_web/live/modal_component.ex
* creating lib/cloe_web/live/live_helpers.ex
* injecting lib/cloe_web.ex
Add the live routes to your browser scope in lib/cloe_web/router.ex:
live "/rooms", RoomLive.Index, :index
live "/rooms/new", RoomLive.Index, :new
live "/rooms/:id/edit", RoomLive.Index, :edit
live "/rooms/:id", RoomLive.Show, :show
live "/rooms/:id/show/edit", RoomLive.Show, :edit
Here is my current cloe_web.ex. I added the import lines suggested in the docs here manually, after which point I got the error. I then added the functions live_view and live_component from here myself to fix the problem. At that point I got this error:
Erlang/OTP 22 [erts-10.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]
Compiling 22 files (.ex)
== Compilation error in file lib/cloe_web/live/room_live/show.ex ==
** (CompileError) lib/cloe_web/live/room_live/show.html.leex:4: undefined function live_modal/3
(elixir) src/elixir_locals.erl:98: :elixir_locals."-ensure_no_undefined_local/3-lc$^0/1-0-"/2
(elixir) src/elixir_locals.erl:99: anonymous fn/3 in :elixir_locals.ensure_no_undefined_local/3
(stdlib) erl_eval.erl:680: :erl_eval.do_apply/6
(elixir) lib/kernel/parallel_compiler.ex:229: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7
so I also added the two import lines within live_view to get what I have now:
defmodule CloeWeb do
@moduledoc """
The entrypoint for defining your web interface, such
as controllers, views, channels and so on.
This can be used in your application as:
use CloeWeb, :controller
use CloeWeb, :view
The definitions below will be executed for every view,
controller, etc, so keep them short and clean, focused
on imports, uses and aliases.
Do NOT define functions inside the quoted expressions
below. Instead, define any helper function in modules
and import those modules here.
"""
def controller do
quote do
use Phoenix.Controller, namespace: CloeWeb
import Plug.Conn
import CloeWeb.Gettext
import Phoenix.LiveView.Controller
alias CloeWeb.Router.Helpers, as: Routes
end
end
def view do
quote do
use Phoenix.View,
root: "lib/cloe_web/templates",
namespace: CloeWeb
# Import convenience functions from controllers
import Phoenix.Controller, only: [get_flash: 1, get_flash: 2, view_module: 1]
import Phoenix.LiveView.Helpers
import CloeWeb.LiveHelpers
# Include shared imports and aliases for views
unquote(view_helpers())
end
end
def live_view do
quote do
use Phoenix.LiveView,
layout: {CloeWeb.LayoutView, "live.html"}
import Phoenix.LiveView.Helpers
import CloeWeb.LiveHelpers
unquote(view_helpers())
end
end
def live_component do
quote do
use Phoenix.LiveComponent
unquote(view_helpers())
end
end
def router do
quote do
use Phoenix.Router
import Plug.Conn
import Phoenix.Controller
import Phoenix.LiveView.Router
end
end
def channel do
quote do
use Phoenix.Channel
import CloeWeb.Gettext
end
end
defp view_helpers do
quote do
# Use all HTML functionality (forms, tags, etc)
use Phoenix.HTML
# Import basic rendering functionality (render, render_layout, etc)
import Phoenix.View
import CloeWeb.ErrorHelpers
import CloeWeb.Gettext
alias CloeWeb.Router.Helpers, as: Routes
end
end
@doc """
When used, dispatch to the appropriate controller/view/etc.
"""
defmacro __using__(which) when is_atom(which) do
apply(__MODULE__, which, [])
end
end
The issue is that the LiveView installation is just enough to install LiveView, but it is not enough to use the phx.gen.live generators. I will add the missing steps, thanks for reporting.
Thanks @josevalim! I looked at your docs changes and applied what you suggested to my site. There seemed to be one more line I needed. With your code in lib/cloe_web.ex I was getting:
Erlang/OTP 22 [erts-10.5] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]
Compiling 20 files (.ex)
== Compilation error in file lib/cloe_web/live/room_live/show.ex ==
** (CompileError) lib/cloe_web/live/room_live/show.html.leex:4: undefined function live_modal/3
(elixir) src/elixir_locals.erl:98: :elixir_locals."-ensure_no_undefined_local/3-lc$^0/1-0-"/2
(elixir) src/elixir_locals.erl:99: anonymous fn/3 in :elixir_locals.ensure_no_undefined_local/3
(stdlib) erl_eval.erl:680: :erl_eval.do_apply/6
(elixir) lib/kernel/parallel_compiler.ex:229: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/7
I added import CloeWeb.LiveHelpers to 'view_helpers' in lib/cloe_web.ex and that fixed it.
Thank you for your help, I'm really enjoying learning Phoenix and LiveView, so thank you for all your work on it!
Most helpful comment
Thanks @josevalim! I looked at your docs changes and applied what you suggested to my site. There seemed to be one more line I needed. With your code in
lib/cloe_web.exI was getting:I added
import CloeWeb.LiveHelpersto 'view_helpers' inlib/cloe_web.exand that fixed it.Thank you for your help, I'm really enjoying learning Phoenix and LiveView, so thank you for all your work on it!