Communication between nested LiveViews (parent -> child)

I have a pretty complex page set up as follows:

Index (LiveView) -> Modal (LiveView) -> a few LiveComponents

This is the ideal structure as the LiveComponents need to update the modal state (with send self()) and once the modal completes, it sends a message to the parent Index view (with send socket.parent_pid).

The problem is that there is no way for the parent Index view to communicate with the child Modal, i.e. to open it. In other words, there is no way to know the pid of children live views, as this would simply solved by sending a message to the Modal process.

Is this a planned feature? How do we communicate from a parent to a child LiveView?

Note: I can make this work by making the Modal into a LiveComponent itself, but then the data flow becomes much more complex, as down the tree the inner components need to use send_update to update the Modal state, whereas having the Modal as a liveview makes the communication flow simpler to follow by using normal messaging.

I mean, this works but it’s ugly :slight_smile:

# Child
def mount(_, _, socket) do
  send socket.parent_pid, {:child, self()}
  {:ok, socket}
end

# Parent
def handle_info({:child, pid}, socket) do
  {:noreply, assign(socket, :child, pid)} 
  # Now the parent knows the child pid and can communicate with it
end

A blessed way of accessing children LiveView pids by id would be much better.

I just blogged about a few different options here: https://thepugautomatic.com/2020/08/communicating-between-liveviews-on-the-same-page/

Would be interesting to have a blessed way of accessing child PIDs like you suggest. Since an explicit :id is mandatory for child live views, I guess it could be based on that. socket.child_pids["my_child_id"] or whatever.

The child PIDs won’t be available yet in some places, e.g. calling handle_params before the children have mounted. Probably not a blocker if documented.

If implemented as in your example, it would also add one send per child even if it’s never used. No idea if that’s always negligible or not. It’s possible that LiveView could get around that by stowing away the PID when spawning the child. Haven’t looked at the implementation to know if that’s feasible.

1 Like