Open w0rd-driven opened 1 year ago
Exception:
** (ArgumentError) cannot convert component BeatseekWeb.Components.NotificationBadge with id "notificationBadge" to HTML.
A component must always be returned directly as part of a LiveView template.
For example, this is not allowed:
<%= content_tag :div do %>
<.live_component module={SomeComponent} id="myid" />
<% end %>
That's because the component is inside `content_tag`. However, this works:
<div>
<.live_component module={SomeComponent} id="myid" />
</div>
Components are also allowed inside Elixir's special forms, such as
`if`, `for`, `case`, and friends.
<%= for item <- items do %>
<.live_component module={SomeComponent} id={item} />
<% end %>
However, using other module functions such as `Enum`, will not work:
<%= Enum.map(items, fn item -> %>
<.live_component module={SomeComponent} id={item} />
<% end %>
(phoenix_live_view 0.18.3) lib/phoenix_live_view/engine.ex:20: Phoenix.HTML.Safe.Phoenix.LiveView.Component.to_iodata/1
(phoenix_live_view 0.18.3) lib/phoenix_live_view/engine.ex:144: Phoenix.HTML.Safe.Phoenix.LiveView.Rendered.to_iodata/3
(phoenix 1.7.0-rc.1) lib/phoenix/controller.ex:958: anonymous fn/5 in Phoenix.Controller.template_render_to_iodata/4
(telemetry 1.2.0) /Users/Shared/repositories/personal/phoenix/beatseek/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
(phoenix 1.7.0-rc.1) lib/phoenix/controller.ex:924: Phoenix.Controller.render_and_send/4
(beatseek 0.1.0) lib/beatseek_web/controllers/page_controller.ex:1: BeatseekWeb.PageController.action/2
(beatseek 0.1.0) lib/beatseek_web/controllers/page_controller.ex:1: BeatseekWeb.PageController.phoenix_controller_pipeline/2
(phoenix 1.7.0-rc.1) lib/phoenix/router.ex:425: Phoenix.Router.__call__/2
(beatseek 0.1.0) lib/beatseek_web/endpoint.ex:1: BeatseekWeb.Endpoint.plug_builder_call/2
(beatseek 0.1.0) lib/plug/debugger.ex:136: BeatseekWeb.Endpoint."call (overridable 3)"/2
(beatseek 0.1.0) lib/beatseek_web/endpoint.ex:1: BeatseekWeb.Endpoint.call/2
(phoenix 1.7.0-rc.1) lib/phoenix/endpoint/sync_code_reload_plug.ex:22: Phoenix.Endpoint.SyncCodeReloadPlug.do_call/4
(plug_cowboy 2.6.0) lib/plug/cowboy/handler.ex:11: Plug.Cowboy.Handler.init/2
(cowboy 2.9.0) /Users/Shared/repositories/personal/phoenix/beatseek/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
(cowboy 2.9.0) /Users/Shared/repositories/personal/phoenix/beatseek/deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3
(cowboy 2.9.0) /Users/Shared/repositories/personal/phoenix/beatseek/deps/cowboy/src/cowboy_stream_h.erl:295: :cowboy_stream_h.request_process/3
(stdlib 4.1.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
Code:
lib/phoenix_live_view/engine.ex
15 assigns: map()
16 }
17
18 defimpl Phoenix.HTML.Safe do
19 def to_iodata(%{id: id, component: component}) do
20> raise ArgumentError, """
21 cannot convert component #{inspect(component)} with id #{inspect(id)} to HTML.
22
23 A component must always be returned directly as part of a LiveView template.
24
25 For example, this is not allowed:
lib/phoenix_live_view/engine.ex
139 def to_iodata(other) do
140 other
141 end
142
143 defp to_iodata([static_head | static_tail], [dynamic_head | dynamic_tail], acc) do
144> to_iodata(static_tail, dynamic_tail, [to_iodata(dynamic_head), static_head | acc])
145 end
146
147 defp to_iodata([static_head], [], acc) do
148 Enum.reverse([static_head | acc])
149 end
lib/phoenix/controller.ex
953
954 defp template_render_to_iodata(view, template, format, assigns) do
955 metadata = %{view: view, template: template, format: format}
956
957 :telemetry.span([:phoenix, :controller, :render], metadata, fn ->
958> {Phoenix.Template.render_to_iodata(view, template, format, assigns), metadata}
959 end)
960 end
961
962 defp prepare_assigns(conn, assigns, template, format) do
963 assigns = to_map(assigns)
/Users/Shared/repositories/personal/phoenix/beatseek/deps/telemetry/src/telemetry.erl
316 EventPrefix ++ [start],
317 #{monotonic_time => StartTime, system_time => erlang:system_time()},
318 merge_ctx(StartMetadata, DefaultCtx)
319 ),
320
321> try {_, #{}} = SpanFunction() of
322 {Result, StopMetadata} ->
323 StopTime = erlang:monotonic_time(),
324 execute(
325 EventPrefix ++ [stop],
326 #{duration => StopTime - StartTime, monotonic_time => StopTime},
lib/phoenix/controller.ex
919 end
920
921 defp render_and_send(conn, format, template, assigns) do
922 view = view_module(conn, format)
923 conn = prepare_assigns(conn, assigns, template, format)
924> data = render_with_layouts(conn, view, template, format)
925
926 conn
927 |> ensure_resp_content_type(MIME.type(format))
928 |> send_resp(conn.status || 200, data)
929 end
lib/beatseek_web/controllers/page_controller.ex
1> defmodule BeatseekWeb.PageController do
2 use BeatseekWeb, :controller
3
4 def home(conn, _params) do
5 # The home page is often custom made,
6 # so skip the default app layout.
lib/beatseek_web/controllers/page_controller.ex
1> defmodule BeatseekWeb.PageController do
2 use BeatseekWeb, :controller
3
4 def home(conn, _params) do
5 # The home page is often custom made,
6 # so skip the default app layout.
lib/phoenix/router.ex
420 :telemetry.execute([:phoenix, :router_dispatch, :stop], measurements, metadata)
421 halted_conn
422
423 %Plug.Conn{} = piped_conn ->
424 try do
425> plug.call(piped_conn, plug.init(opts))
426 else
427 conn ->
428 measurements = %{duration: System.monotonic_time() - start}
429 metadata = %{metadata | conn: conn}
430 :telemetry.execute([:phoenix, :router_dispatch, :stop], measurements, metadata)
lib/beatseek_web/endpoint.ex
1> defmodule BeatseekWeb.Endpoint do
2 use Phoenix.Endpoint, otp_app: :beatseek
3
4 # The session will be stored in the cookie and signed,
5 # this means its contents can be read but not tampered with.
6 # Set :encryption_salt if you would also like to encrypt it.
lib/plug/debugger.ex
No code available.
lib/beatseek_web/endpoint.ex
1> defmodule BeatseekWeb.Endpoint do
2 use Phoenix.Endpoint, otp_app: :beatseek
3
4 # The session will be stored in the cookie and signed,
5 # this means its contents can be read but not tampered with.
6 # Set :encryption_salt if you would also like to encrypt it.
lib/phoenix/endpoint/sync_code_reload_plug.ex
17
18 def call(conn, {endpoint, opts}), do: do_call(conn, endpoint, opts, true)
19
20 defp do_call(conn, endpoint, opts, retry?) do
21 try do
22> endpoint.call(conn, opts)
23 rescue
24 exception in [UndefinedFunctionError] ->
25 case exception do
26 %UndefinedFunctionError{module: ^endpoint} when retry? ->
27 # Sync with the code reloader and retry once
lib/plug/cowboy/handler.ex
6 def init(req, {plug, opts}) do
7 conn = @connection.conn(req)
8
9 try do
10 conn
11> |> plug.call(opts)
12 |> maybe_send(plug)
13 |> case do
14 %Plug.Conn{adapter: {@connection, %{upgrade: {:websocket, websocket_args}} = req}} = conn ->
15 {handler, state, cowboy_opts} = websocket_args
16 {__MODULE__, copy_resp_headers(conn, req), {handler, state}, cowboy_opts}
/Users/Shared/repositories/personal/phoenix/beatseek/deps/cowboy/src/cowboy_handler.erl
32 -optional_callbacks([terminate/3]).
33
34 -spec execute(Req, Env) -> {ok, Req, Env}
35 when Req::cowboy_req:req(), Env::cowboy_middleware:env().
36 execute(Req, Env=#{handler := Handler, handler_opts := HandlerOpts}) ->
37> try Handler:init(Req, HandlerOpts) of
38 {ok, Req2, State} ->
39 Result = terminate(normal, Req2, State, Handler),
40 {ok, Req2, Env#{result => Result}};
41 {Mod, Req2, State} ->
42 Mod:upgrade(Req2, Env, Handler, State);
/Users/Shared/repositories/personal/phoenix/beatseek/deps/cowboy/src/cowboy_stream_h.erl
301 end.
302
303 execute(_, _, []) ->
304 ok;
305 execute(Req, Env, [Middleware|Tail]) ->
306> case Middleware:execute(Req, Env) of
307 {ok, Req2, Env2} ->
308 execute(Req2, Env2, Tail);
309 {suspend, Module, Function, Args} ->
310 proc_lib:hibernate(?MODULE, resume, [Env, Tail, Module, Function, Args]);
311 {stop, _Req2} ->
/Users/Shared/repositories/personal/phoenix/beatseek/deps/cowboy/src/cowboy_stream_h.erl
290 %% to simplify the debugging of errors. The proc_lib library
291 %% already adds the stacktrace to other types of exceptions.
292 -spec request_process(cowboy_req:req(), cowboy_middleware:env(), [module()]) -> ok.
293 request_process(Req, Env, Middlewares) ->
294 try
295> execute(Req, Env, Middlewares)
296 catch
297 exit:Reason={shutdown, _}:Stacktrace ->
298 erlang:raise(exit, Reason, Stacktrace);
299 exit:Reason:Stacktrace when Reason =/= normal, Reason =/= shutdown ->
300 erlang:raise(exit, {Reason, Stacktrace}, Stacktrace)
proc_lib.erl
No code available.
%{}
%{"_csrf_token" => "ty8L2MxQrpbP_IxVN4XMe1uX"}
@current_user
to even pull the logout link or the profile sections out of the sidebar, we need to use live_session and mount the auth on every view.This was handled rather easily once I thought things through. The existing home page is a perfect representation of a landing page that needs its own layout. The work required to make that work with an essentially hidden sidebar that still throws errors about rendering isn't worth it. It's possible this is a bug though.