I have a LiveComponent which I’ve broken out into a parent and a few child components. Currently I have phx-click handlers elsewhere in the app which are using phx-target to despatch events to the parent. In the new setup, these events aren’t being passed on to the child LiveComponents, instead being handled (and consequently crashed) by the parent. Is this expected behaviour? Have been scouring the documentation but haven’t been able to find anything definitive about how and whether events are delegated down component trees.
I see some ambiguity in your post that makes it difficult to say whether this is expected behavior. You said phx-target dispatches the events to the parent, but then you’re surprised when they are handled by the parent, and you expect them to go to the child. This seems like a miscommunication somewhere.
For now I will say that in several of my apps I have a setup with hierarchy like:
LiveView -> parent component -> child component
The child fires an event with no target, which ends up at the LV where it is handled. The LiveView updates an assign, which is passed down to the parent component like:
<%= live_component @socket, MyApp.ParentComponent, my_assign: @my_assign %>
and then the parent passes the assign to the child in a similar way.
This way the LiveView is the source of truth, it handles all the events, and all of your components get automatically updated, no matter how they are nested. So far I haven’t encountered a reason to switch away from this design (i.e. performance, limitations) but perhaps others might have a contrasting experience to share.
If you do phx-target = @myself on your phx-click elements, it should send the event to your child component. However I am currently trying to make it work with hooks and haven’t figured that out yet…
Thanks for replying. Sorry, I think I was a little bit unclear: the
phx-click is being sent from outside the LiveComponent, but within the same LiveView. The event is currently being sent to the parent component, but I want it to be responded to by the child. It’s been a while, but I guess based on previous experiece with UI frameworks, particularly UIKit, I’d expect it to be passed down…but I’m guessing that’s not happening here? Is there any passing of events from parent to child automatically in LV, or do you need to explicitly send things to the places they’re meant to go?
So, done a bit more testing. I tried to explicitily set the
id of the child live-component then use the same string as the phx-target, but this didn’t work either as the id was overridden by liveview. Is there another way to set a unique id for phx-target?
You need to explicitly state the target if it is not the LiveView. If it is a stateful component you have to give it an id. You can use
@myself within a stateful component to target itself. If you want it to go somewhere else, you need to omit the target or use
send(self(), ...) to send it to the LiveView, or
send_update(SomeComponentModule, id: "components_id", some_assign: 42) if you want it to go to another component.
You can see
send_update in use in the Surface docs here
Most importantly, have a read of this page of the docs.
Phoenix.LiveComponent — Phoenix LiveView v0.15.7 (hexdocs.pm))
Thanks, have just worked this one out. LiveComponent id != DOM id… but sometimes it is. Quite confusing