crn

crn

Emit LiveComponent event to both the LiveComponent as well as its parent LiveView

Hello fellow Elixters :wave:

I am quite new to Phoenix LiveView and just started testing Surface UI. So far, it all feels very natural and well-designed. So kudos to everyone involved in building it! :slight_smile:

Now I got stuck with something I expect to be a fairly easy and common problem.

Situation

I have a LiveView with a nested LiveComponent. For the sake if this example, let’s say the LiveComponent renders a card which should be highlighted when selected (clicked). The LiveComponent should therefore emit an event when clicked. This event should be handled both in the LiveComponent to toggle the highlighting as well as optionally within the LiveView to, say, track which cards are selected.

First of all: Does it at least make sense what I am trying to do? :slight_smile:

Second: Currently I see two possible ways to implement it:

  1. Emit the event with the LiveComponent as its target (i.e., phx-target={@myself} in plain LiveView, or on-click="my-click-event" in Surface UI). Then inside handle_event/3 toggle the card highlight, forward the event with send(self(), ...) to the LiveView and, in there, handle it in handle_info/2. This works, but has the drawback that the LiveComponent’s parent must handle the message with handle_info/2 unless it wants its mailbox to fill up. Moreover, it would feel so much more natural if I handle the message from LiveComponent in the LiveView’s handle_event/3 as well.
  2. Emit the event and make the LiveComponent’s parent the target – that is, the LiveView (in Surface UI via prop my_click, :event in the LiveComponent and on-click={@my_click} inside render/1). There, catch the event in handle_event/3 and use send_update/3 to cause the LiveComponent to toggle the card’s highlight. Has the (IMHO) severe architectural drawback that the parent (here: LiveView) has to do the wiring so that the child (here: LiveComponent) renders as expected. Definitely don’t want to go down this road.

Both variants don’t feel too good to me. Essentially, what I would like to do is to somehow configure the phx-click (or :on-click in Surface UI) to target both the LiveComponent as well as the LiveView. Is that somehow possible?

Or: What’s the LiveView-idiomatic way to implement my scenario?

Best
Carsten

Marked As Solved

trisolaran

trisolaran

I don’t think this is true. Messages that go to your LiveView are handled here. If your view defines a handle_info callback, and it doesn’t handle the message that was just received, your view will simply crash. If your view doesn’t define a handle_info, a warning is emitted (but the message was still handled). Either way the mailbox won’t fill up.

I’m assuming that you need a LiveComponent to isolate state handling and logic and that function components are not a desirable option. I say this because in your specific example you could get away with a function component and put all state handling in the LiveView, but I presume your example is an oversimplification of something else.

I generally use a combination of (1) and (2): events from the LiveComponent are forwarded to the LiveView by sending a message, and if the LiveView has to communicate something to the LiveComponent, it does so using send_update/3 (it’s all message passing anyway under the hood).

I totally agree. I think this is a drawback of the current architecture. LiveComponents should be able to emit events for their parents IMO. I believe Chris McCord mentioned a rethinking of the API to communicate between LiveViews and LiveComponents as ongoing work in his last ElixirConf talk, so maybe something will happen there soon :crossed_fingers:

Also Liked

cmo

cmo

How do you avoid handling this message and filling up the mailbox?

I wouldn’t get caught up on handle_event vs handle_info. You’re likely to end up with plenty of handle_info in the long run. All your PubSub messages, messages to self, messages from other processes will land there.

Another option is to use function components or stick with livecomponents and have highlighted as an assign, handling state in the liveview.

If you go the send_update route, you can define a function on the component that wraps send_update, e.g. Card.highlight(id).

Where Next?

Popular in Questions Top

New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
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
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
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
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
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Other popular topics Top

malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
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
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
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

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement