Component1 calls handle_event on Component2, but no render happens

I am struggling to send a message between 2 components.

It’s a calendar. User clicks on the “day box” in order to see the details for that day (which is driven by a different component).

ComponentDayView receives the initial event that the user wants to see the details for that particular day. It then calls the handle_event function on ComponentViewController:

ComponentDayView ...

def handle_event("day-view", params, socket) do
    # forward to ComponentViewController for handling
    ComponentViewController.handle_event("day-view", params, socket)
    {:noreply, socket}

ComponentViewController receives that handle_event message just fine. It does all of the processing it needs BUT … render never happens on that component. So the view never changes.

They are both in the same LiveView, so I should be able to send messages between the two. I can’t use send_update because the update function on ComponentViewController sets defaults when it is first called by the LiveView. So those defaults will just override the payload in send_update.

I also tried setting the phx-target in ComponentDayView to go directly to ComponentViewController, but this also didn’t work:

render in ComponentDayView that captures user's click on the "day box" 

    <td phx-click="day-view" phx-target="#view_controller_id" phx-value-date={Timex.format!(@day, "%Y-%m-%d", :strftime)} class={@day_class}>

Calling handle_event directly on the second component would be the most efficient approach.

Why doesn’t render get called on that component if another component calls handle_event via a function call?

Don’t think you can do that, calling other Component’s Handle Event. :slight_smile:
Think you need to go through the parent liveview and then have the parent live_view send_update to the desired child.

I found the answer to how to communicate between two components in another ElixirForum post. See the explanation provided by @sfusato in this post.

Here is the final solution in my code:
ComponentDayView receives a handle_event when the user clicks on the calendar box to view that day’s details. It then sends an update to the ComponentViewController to display that day:


def handle_event("day-view", %{"date" => date}, socket) do

    # forward to ComponentViewController for handling
        id: socket.assigns.view_controller_id,
        update: :show_day_view,
        date: date)
    {:noreply, socket}

ComponentViewController receives this using a second implementation of update that uses pattern matching to just update this new assign. This “update” function simply calls another function that does all of the logic to set up the day view and then render is automatically called:

ComponentViewController ...
@impl true
  def update(%{update: :show_day_view, date: date}, socket) do
    {:ok, update_day_view(socket, date)}

Works beautifully. Thank you @sfusato for your answer in that other post!!!