Livecomponent: assign @value not available in eex template. Why such behaviour?

I have created a liveview with a child livecomponent (dialog). I was expecting to be able to define assigns in the child mount function but I get the error:

assign @value not available in eex template.
Please make sure all proper assigns have been set. If this
is a child template, ensure assigns are given explicitly by
the parent template as they are not automatically forwarded.

I was expecting this to work since I assign :value is in the mount function of the child component. Though, the error message suggests that the value has to be “forwarded” by the parent liveview in this case. If this is the case, I don’t understand what are the benefits of livecomponents since part of the logic still has to remain in the parent liveview with values passed to the child component when needed.

On the other hand, using two liveviews for this use case does not seem optimal as it would require the usage of PubSub. The latter seems to be more suited for broadcasting which is not something useful for simple component interactions (eg. show/hide).

Livecomponents examples I found just show simple use of them where one or two values are passed to the component but nothing with more complex livecomponents.

Thanks.

Are you components “stateless” or “stateful”? If “stateless” try updating your components socket assigns in the update callback rather than the mount.

can you post code? not sure I understand…

either way see this - which might be helpful…

Hi,

It doesn’t seem that Livecomponent can have internal state. It’s not possible to define value only in the child component. It needs to be defined in the parent template and included in the <%= live_component @socket, value: ....
In the link you posted, StatefulComponent can update title but title is included in

<%= live_component(
          @socket,
          DemoWeb.StatefulComponent,
          id: "1",
          title: @title
        )
    %>

It isn’t possible to use title in the StatefulComponent without being included in live_component.

Thanks for the link. The problem with such examples is that they only show simple use cases.

I am using stateful components. From what I have tried I get to that same conclusion that the live_component cannot have declare internal values. That’s why I don’t understand the benefits of live_components.

What have you tried to come to that conclusion. The docs (https://hexdocs.pm/phoenix_live_view/Phoenix.LiveComponent.html) discuss stateful components managing their own state.

You need to pass in an id in the assigns for a component to be stateful. I have only done a simple test - adding a button to a component that increments a counter when it is clicked. But I can have multiple instances of the same component on the same liveview tracking their own counter - I assume that’s what you mean by declaring their own internal values.

You are right and I did some more research and found an example where the live_component declares its own values:

So it is possible and my conclusion was mostly based on the fact that there are not any examples of this usage.
The reason for which it didn’t work in my project was my fault. I copy pasted the mount definition from my LiveView in my component. However, there is a subtle difference in the mount function for the LiveView and the one for the LiveComponent.

LiveComponent:
def mount(socket) do

LiveView:
def mount(_session, socket) do

So my mount definition was wrong and the value was never added to the assigns.

Thanks to everyone who took the time to help me.

4 Likes