akramic
November 11, 2024, 10:15am
1
I’m struggling with passing values to nested function components.
My feeling was that passing ‘user’ from the parent to the child as shown below would work.
However it doesn’t and the compiler complains that variable ‘user’ is undefined.
defmodule MyAppWeb.Playground.Nested do
use MyAppWebWeb, :live_view
@impl true
def mount(_params, _session, socket) do
IO.inspect(socket.assigns.current_user)
{:ok, socket}
end
@impl true
def render(assigns) do
~H"""
<div class="flex items-center justify-center">
<div>
<p>Main container</p>
<.parent user={@current_user}>
<:child let={user}>
<.child />
</:child>
</.parent>
</div>
</div>
"""
end
slot :child, required: true
attr :user, :map, required: true
def parent(assigns) do
~H"""
<div>
Parent <pre><%= inspect(@user, pretty: true) %></pre>
<%= render_slot(@child, @user) %>
</div>
"""
end
attr :user, :map, required: true
def child(assigns) do
~H"""
<div>
Child <pre><%= inspect(@user, pretty: true) %></pre>
</div>
"""
end
end
The docs seem to only use one example - a table with multiple rows and columns for which a for expression is used.
I’m sure I am not grokking something simple as we should easily be able to compose complex UIs from composing simple function components.
I’d be very grateful for any pointers.
Thanks.
<.parent user={@current_user}>
<:child let={user}>
<.child user={user} />
</:child>
</.parent>
You need to pass the user to .child
. let
just gives you a place to bind variables, you still need to use them explicitly.
akramic
November 11, 2024, 10:37am
3
Thanks for the reply @LostKobrakai , that makes sense. However, after making the change to:
<.parent user={@current_user}>
<:child let={user}>
<.child user={user} />
</:child>
</.parent>
I still get the error :
error: undefined variable "user"
for both
<:child let={user}>
and
The full example is now :
defmodule MyAppWeb.Playground.Nested do
use MyAppWeb, :live_view
@impl true
def mount(_params, _session, socket) do
IO.inspect(socket.assigns.current_user)
{:ok, socket}
end
@impl true
def render(assigns) do
~H"""
<div class="flex items-center justify-center">
<div>
<p>Main container</p>
<.parent user={@current_user}>
<:child let={user}>
<.child user={user} />
</:child>
</.parent>
</div>
</div>
"""
end
slot :child, required: true
attr :user, :map, required: true
def parent(assigns) do
~H"""
<div>
Parent <pre><%= inspect(@user, pretty: true) %></pre>
<%= render_slot(@child, @user) %>
</div>
"""
end
attr :user, :map, required: true
def child(assigns) do
~H"""
<div>
Child <pre><%= inspect(@user, pretty: true) %></pre>
</div>
"""
end
end
Very frustrating.
I feel it’s got to be some simple idiotic error I’m making - but for the life in my can’t see where.
Many thanks.
Yeah, didn’t notice it at first, but :let=
vs let=
. You need the former.
2 Likes
akramic
November 11, 2024, 10:51am
5
akramic
November 11, 2024, 11:39am
6
Hi Benjamin
I’m very grateful for your help in resolving this.
As you can probably tell, I’m not a developer - I work as a family physician and am interested in Elixir and Phoenix as tools for a couple of projects.
I’ve found the community to be wonderfully welcoming and very generous with their time.
Once again, I’m very grateful that you took the time to look at this and help.
3 Likes