Handle_event in live component

Hello everyone! I read in Phoenix live view docs it is generally a good idea to handle events in a component, not in parent live view, cause the server sends new data only needed for component and this helps UX in general. So I decided to add form validation to my live component:

def handle_event("validate", %{"user" => %{"email" => email}}, socket) do

That is how my form validating is happening in parent LiveView. My first move was to put phx-target on form. After that I have got an error about my second argument in handle_event function:
(KeyError) key :user not found in: %{_changed_: %{}, … , user_changeset: #Ecto.Changeset<action: nil, changes: %{}, errors: [username: {“can’t be blank”, [validation: :required]}], data: #MyApp.Accounts.User<>, valid?: false>}

As you can see in the error log there is no :user key. Maybe there is something about my changeset? I declare it in part LiveView mount then pass it to Component. If it is - is it so bad to initialize changeset both in Live Component and parent Live View?

Please post the code related to the error stack.

Like this the error is related to some code not shown, and we cannot guess what it is.

Do you mean full handle_event?

  def handle_event("validate", %{"user" => %{"email" => email}}, socket) do
    cset =
      socket.assigns.user
      |> User.changeset(email)
      |> Ecto.Changeset.cast_assoc(:users_personal, with: &UserPersonal.changeset/2)
      |> Map.put(:action, :update)

    {:noreply, assign(socket, user_changeset: cset)}
  end

here is the mount function:

  @defaults %{
    show: false,
    enter_duration: 300,
    leave_duration: 200,
    background_color: "bg-gray-500",
    background_opacity: "opacity-75",
    title_color: "text-gray-900",
    body_color: "text-gray-500",
    left_button: nil,
    left_button_action: nil,
    left_button_param: nil,
    right_button: nil,
    right_button_action: nil,
    right_button_param: nil,
  }

  @impl Phoenix.LiveComponent
  def mount(socket) do
    {:ok, assign(socket, @defaults)}
  end

and that is how my live view calls the component:

<%= live_component MyApp.Components.ModalComponent,
                     id: :modal_email,
                     title: "Change your email",
                     body: "For that we need your current password and your new email",
                     show: @live_action == :change_email,
                     user_changeset: @user_changeset,
                     right_button: "Change",
                     right_button_action: "change-email",
                     left_button: "Cancel",
                     left_button_action: "cancel-change-email"%>

There should be a filename and the line where the error occurs in the error stack…

Probably, it’s in the User or the UserPersonal schema.

Where it expects a :user key…

1 Like

Found this error: it was expecting the user struct, but I did not pass it to the live component
Thank you!

1 Like