Is this right? send self() AND send_update to push data up to parent

VERSIONS: phoenix 1.6.6 phoenix_live_view 0.17.9

CONTEXT: I have a child component that collects country, state_region and city data and returns a geo_point (with timezone, latlong, etc). The parent can either be a LiveView OR another component.

ISSUE: Using send self() always sends the data up to the LiveView, but I need it to sometimes go to another component. So now I have the code below to switch between send self() and send_update depending on the parent_type. It also means that to use this component, the parent liveview or component must set a “parent_type” assign of either “component” or “liveview.”

This works but seems a bit clunky to me. Am I doing this right?

defp notify_parent(socket) do

    data =  { %{"geo_status" => socket.assigns.geo_status,
                "geo_point" => socket.assigns.geo_point,
                "country" => socket.assigns.country,
                "state" => socket.assigns.state,
                "city" => socket.assigns.city }}

    case socket.assigns.parent_type do
      "liveview" -> send self(), {:geo_data, data}
      "component" ->  send_update(socket.assigns.module,
                      id: socket.assigns.parent_id,
                      update: :geo_data, data: data)
    end
    socket
  end
4 Likes

This is indeed a bit clunky, but it’s also correct as far as I know.

2 Likes

I did it the same way.

1 Like

This works but seems a bit clunky to me. Am I doing this right?

I would say it’s very clunky. A component shouldn’t have to know who its parent is in order to communicate with it, there should be one API. But, as @benwilson512 said, this is currently the right way.

Unifying the API for communicating with LiveViews and LiveComponents is AFAIK ongoing work and was mentioned by Chris McCord during his talk at Elixirconf 2022.

3 Likes

Related Github issue: Provide a unified mechanism to message the parent/child · Issue #1597 · phoenixframework/phoenix_live_view · GitHub

1 Like

Can’t you put an assign @target which defaults to @myself and use that to discriminate?
Just thinking out loud

Cheers

@myself is nil in the case of a LiveView or a Phoenix.LiveComponent.CID struct in the case of a live component but IMHO the send_update/3 function needs another kind of id for its id key in the assigns. Also we need to provide the module as part of the call. Thus I don’t know how to use @myself to solve the problem. I ended up using the notify_parent function by @annad .

The github issue has been marked as solved by José. Chris gave the right way to send data from a component to a LV or LC and José added that they planned to add send_update(@myself, ...) which has been done in LiveView 0.20.0. All of this closes the issue permanently. I updated my code to use the technique proposed by Chris.