I’m trying to define a macro to dynamically create render/1 calls in my LiveView and having some trouble.
I did find this but mine includes calling live_component within the sigil which is what seems to be causing the problem.
What I’m trying to do is this:
defmodule MyAppWeb.Macros do
defmacro defrender(component, slug, id) do
quote do
@impl true
def render(%{slug: unquote(slug)} = var!(assigns)) do
~H"""
<%= live_component unquote(component), id: unquote(id) %>
"""
end
end
end
end
…and then in my LiveView:
defmodule MyAppWeb.PageLive do
use MyAppWeb, :live_view
import MyAppWeb.Macros
# def mounts, updates, handle_events, etc....
defrender(MyAppWeb.Blog, "blog", "blog")
end
I end up with a compile error: unquote called outside quote.
I’ve tried various uses and combos of var! and unquote! inside the render function, but my mental model here is still very weak. I sort of understand that I have a macro within a macro here, but it’s making my brain explode.
The stakes are low here, of course. I’m mostly trying to figure this out for learning purposes.
I believe the immediate problem is you are not using quote in your macro definition.
defmodule MyAppWeb.Macros do
defmacro defrender(component, slug, id) do
quote do
@impl true
def render(%{slug: unquote(slug)} = var!(assigns)) do
~H"""
<%= live_component unquote(component), id: unquote(id) %>
"""
end
end
end
end
Oops! That was actually just a typo on my part—I retyped the whole thing to change some names instead of just changing the names (why did I do this? I dunno, haha). I edited my question to reflect this.
I’ll try out your other suggestions and report back. Thank you for the response!!
In some way try to send the arguments one level up, in order words, do not send them in the macro signature, instead maybe in the mount (in the assigns?). Then in the macro definition inside the ~H sigil use something like:
Doing that the unquote called outside quote should go away. I was working in something similar to your case and getting the same error like you. I did what I mentioned before and it worked. Hope it helps @sodapopcan.