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
    ~L"""
     <%= 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 %>

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

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

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"
…
end

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>

2 Likes

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.

2 Likes

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