Handle_event callback keeps going to LiveView instead of Modal Component

I have tried for days to get this to work and I’ve exhausted the documentation. Could someone help me with this?

ISSUE: handle_event is being called on parent LiveView instead of the Modal Component that should be receiving that callback.

LiveView is called ShowLesson. In the render for ShowLesson, I call a modal called ResourceformLive.ComponentRemoveFromLesson which removes a resource from the Lesson. That code looks like this:

<%= if @live_action in [:remove_resource] do %>
      <%= live_modal @socket, MyApp.ResourceformLive.ComponentRemoveFromLesson,
      id: @lesson_id,
      page_title: @page_title,
      action: @live_action,
      lesson_id: @lesson_id,
      resourceform: @resourceform,
      return_to: Routes.lesson_show_lesson_path(@socket, :show_lesson, @lesson_id) %>
    <% end %>

That code successfully opens the modal component’s render and populates the assigns.

The render for ComponentRemoveFromLesson is very simple. It did not require a changeset, so I just used an atom instead of a changeset. The user confirms the removal of the resource and presses a button. That button should call handle_event on the modal component. Instead, it keeps going to the LiveView.

def render(assigns) do
     <%= f = form_for :join, "#",
      id: "remove-resource",
      phx_target: @myself,
      phx_submit: "remove" %>

      <h2><%= @page_title %></h2>

      <h3>Resource to be Removed</h3>
      <span>Name: <%= link( @resourceform.title, to: @resourceform.resource_url) %></span>
      <span>Description: <%= @resourceform.description %>

      <span>Are you sure you want to remove this resource from your Lesson Plan?"</span>

      <ul><button phx-click="remove">Remove Resource</button></ul>

The modal_component handle_event looks like this:

def handle_event("remove", %{"join" => params}, socket) do
    IO.puts "RESOURCEFORM_LIVE.component_remove_from_lesson.handle_event :remove"

But it never gets to that handle_event, because it keeps going to the ShowLesson Liveivew. I keep getting this error (which is driving me mad):

(UndefinedFunctionError) function MyApp.LessonLive.ShowLesson.handle_event/3 is undefined or private

I can’t figure out why it keeps slinging back to the LiveView for the handle_event callback instead of using the one in the component. I set a unique ID in the component call as you can see above. What am I missing?

You should probably set phx-target on the button too.

1 Like

Hi @annadphx-click is a separate binding that is unrelated to form events. It looks like you have configured the callback to work with the form submit event, but you are shadowing that event with a click event of the same name. I would recommend dropping the phx-click="remove" from the button, which will allow the button to act as a submit button for the form.

PS if you want to be explicit about the button action, do <button type="submit">Remove</button> or use the submit/1 form helper.

PPS if you want to use phx-click on a button within a form be sure to set its type to button: <button type="button" phx-click="foo">Foo!</button>


Thank you @kokolegorille and @mcrumm for your help!

I got it to work by removing the phx-click=“remove”. You were right @mcrumm … I was confusing it by having that in there. I now just have this:

<button> Remove Resource</button>

I tried phx-target to see if that would work, because I had seen that in a document. I tried both of these, but neither worked. It was still sending handle_event to the LiveView:

      <ul><button phx-click="remove" phx_target="<%= @myself %>" > Remove Resource</button></ul>
      <ul><button phx-click="remove" phx_target="remove-resource" > Remove Resource</button></ul>

I suspect I was setting the phx_target incorrectly. I’ll need to read more about form events and how they tie into the callbacks.

Thank you both for replying and helping me solve this! Yay!

1 Like

You want phx-target when you’re writing raw HTML tags - the helpers like form_for handle the conversion from snake_case for you. This is easy to miss! I have done it many times myself.

This is just a friendly suggestion, but I would encourage you once again to always set the type on buttons in a form, because the default button type is submit.


Ahhh. That makes sense since the auto generated code uses “submit.” Thank you for the mentoring! I’ve updated my button code to have type=“submit.”

1 Like