Are nested (to arbitrary level) stateful LiveComponents supported in LiveView?

I have a situation where one stateful LiveComponent is nested inside a parent stateful LiveComponent. I want the child innermost component to handle its own events. But the best I can do is get its parent handle_event/3 to be called. So my question is can LiveComponents which are stateful (have the :id assign) nest to arbitrary levels and still handle their own events or is this not supported?

Here is the code in question with just the relevant parts for illustration:

defmodule AppWeb.Live.AppLive do

  def render(assigns) do
    ~L"""
    <div>
    <%= live_component @socket, AppWeb.Live.Components.Home, id: :home %>
    </div>  
   """
  end
end

defmodule AppWeb.Live.Components.Home do

  def render(assigns) do
    ~L"""
    <div>
    <h1>Home</h1>
    <%= live_component @socket, AppWeb.Live.Components.TextInput, id: :text_input %>
    </div>
    """
  end
end

defmodule AppWeb.Live.Components.TextInput do

  def render(assigns) do
    ~L"""
    <div>
    <%= f = form_for @input_changeset, "#",
      phx_change: :validate,
      phx_submit: :save,
      phx_target: @myself %>
      <%= textarea f, :description %>
      <%= submit "Save" %>
    </form>
    </div>
    """
  end

  def handle_event("validate", params, socket) do
    Logger.info("validate called")
    {:noreply, socket}
  end

end

I’ve tried every way I know but I can’t get handle_event/3 to be called on the innermost child component. If I move it to the parent, it gets called. So am I attempting something that is not supported?

Please try master. There was a bug in my query selector for @myself, where we’d sometimes target the wrong component for a parent with the same internal component ID.

4 Likes

Ah, that addressed my problem too, thx for the post! Is there a roadmap publicly available to LiveView 1.0?

When It’s Ready™

9 Likes

Thanks @chrismccord, I will try this out today if I can. I tried switching to master in my existing project and got some errors that I couldn’t easily resolve. Today I’ll start a fresh project and import the code in question and see if I can get that to work. I’ll let you know how it goes…thanks again!

@chrismccord or anyone else who knows…could you point me to how to install from master? I tried just updating the deps in mix.ex and running mix deps.get but I get the following:

Dependencies have diverged:
* phoenix_pubsub (https://github.com/phoenixframework/phoenix_pubsub)
  the dependency phoenix_pubsub in mix.exs is overriding a child dependency:

  > In mix.exs:
    {:phoenix_pubsub, [env: :prod, git: "https://github.com/phoenixframework/phoenix_pubsub"]}

  > In deps/phoenix/mix.exs:
    {:phoenix_pubsub, "~> 2.0-dev", [env: :prod, git: "https://github.com/phoenixframework/phoenix_pubsub.git"]}

  Ensure they match or specify one of the above in your deps and set "override: true"
* phoenix_html (https://github.com/phoenixframework/phoenix_html)
  the dependency phoenix_html in mix.exs is overriding a child dependency:

  > In mix.exs:
    {:phoenix_html, [env: :prod, git: "https://github.com/phoenixframework/phoenix_html"]}

  > In deps/phoenix/mix.exs:
    {:phoenix_html, "~> 2.13", [env: :prod, repo: "hexpm", hex: "phoenix_html", optional: true]}

  Ensure they match or specify one of the above in your deps and set "override: true"
* phoenix (https://github.com/phoenixframework/phoenix)
  the dependency phoenix in mix.exs is overriding a child dependency:

  > In mix.exs:
    {:phoenix, [env: :prod, git: "https://github.com/phoenixframework/phoenix"]}

  > In deps/phoenix_live_reload/mix.exs:
    {:phoenix, "~> 1.4", [only: :dev, env: :prod, repo: "hexpm", hex: "phoenix"]}

  Ensure they match or specify one of the above in your deps and set "override: true"
** (Mix) Can't continue due to errors on dependencies

I’m probably doing this wrong. What’s the correct way to install from master for all the deps needed for this?

Here are the instructions:

# If you want the latest features, install from GitHub:

def deps do
  [
    {:phoenix_live_view, github: "phoenixframework/phoenix_live_view"},
    {:floki, ">= 0.0.0", only: :test}
  ]

@sfusato thanks! I was able to get master installed and can confirm that it works as expected now.