zoedsoupe

zoedsoupe

How Phoenix.Component can handle events?

While searching and studying about live view I found this page of LiveComponent documentation, and reading more carefully about the “cost of a live component”, here: Phoenix.LiveComponent — Phoenix LiveView v1.2.5

Then it gives a not to do example, using a LiveComponent to wrap DOM events, like:

defmodule MyButton do
  use Phoenix.LiveComponent

  def render(assigns) do
    ~H"""
    <button class="css-framework-class" phx-click="click">
      <%= @text %>
    </button>
    """
  end

  def handle_event("click", _, socket) do
    _ = socket.assigns.on_click.()
    {:noreply, socket}
  end
end

So it preferable to use a functional component! Then, it was I did! I have this function component to wrap and style the native DOM button tag:

  attr :style, :string, values: ~w(primary secondary), required: true
  attr :submit, :boolean, default: false
  attr :icon, :atom, required: false, default: nil
  attr :class, :string, default: ""
  attr :rest, :global, doc: ~s(used for phoenix events like "phx-click" and "phx-target")

  slot :inner_block

  def button(assigns) do
    ~H"""
    <button
      type={if @submit, do: "submit", else: "button"}
      class={["btn", "btn-#{@style}", @class]}
      {@rest}
    >
      <.icon :if={@icon} name={@icon} />

      <.text :if={@style == "primary"} size="base" color="text-white-100">
        <%= render_slot(@inner_block) %>
      </.text>

      <.text :if={@style != "primary"} size="base" color="text-blue-80">
        <%= render_slot(@inner_block) %>
      </.text>
    </button>
    """
  end

To be reusable in any phoenix template with a predefined style. My question is, how this function component can handle events, in this case, phx-click?

I used the button like this: https://github.com/peapescarte/pescarte-plataforma/blob/main/lib/pescarte_web/templates/landing_html/show.html.heex#L56-L58

However no event is trigged as can be seen in this little video:

Marked As Solved

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Hey @zoedsoupe you’re absolutely right, it’s only very recently that Phoenix started using heex for controllers and I basically totally forgot it does that now!

So back to your question: Yea you can only do handle_event and phx-target stuff on components used in a live view. If you do need to use a functional component between both live and traditional views you could probably pass in myself: nil as an assign, but also the button won’t really work.

Also Liked

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

In short, it can’t. In order for a component to receive events it needs to be a stateful component that does use Phoenix.LiveComponent in its own module.

You generally also need to phx-target={@myself} to ensure that the events go to your component.

cmo

cmo

Function components do not handle events. Handle them in the parent liveview or livecomponent.

On a side note, this could be shorter:

<.text :if={@style == "primary"} size="base" color="text-white-100">
   <%= render_slot(@inner_block) %>
</.text>

<.text :if={@style != "primary"} size="base" color="text-blue-80">
  <%= render_slot(@inner_block) %>
</.text>

Could be:

<.text size="base" color={if @style == "primary", do: "text-white-100", else: "text-blue-80">
   <%= render_slot(@inner_block) %>
</.text>
benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Not in the way you’re looking for that I see. That said if you read Components and HEEx — Phoenix v1.8.8 and the other docs it links to, you’ll notice that the word event never even appears. It’s only when you get to the live view docs do you start seeing events and handle_event.

Last Post!

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Not in the way you’re looking for that I see. That said if you read Components and HEEx — Phoenix v1.8.8 and the other docs it links to, you’ll notice that the word event never even appears. It’s only when you get to the live view docs do you start seeing events and handle_event.

Where Next?

Popular in Questions Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

Other popular topics Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 44532 311
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New

We're in Beta

About us Mission Statement