Redirect after flash in a component

I have a LiveComponent that I use in multiple locations in my app. I want to flash a message from within handle_event. As far as I understand I need to redirect after I flash, to flush the flash to the connection/socket. Like this:

def handle_event("do_something", _, socket) do
  # do something here
  {:noreply,
    socket
    |> put_flash(:success, "Success")
    |> push_redirect(to: <TODO>)
end

What do I put in the to: in the redirect, so it’s always the “current path”, no matter where I use the component? Do I need to pass down the current path from the handle_params of the parent, or is there a smarter way?

You could potentially pass a return_to assign from the parent LiveView.

{:noreply,
    socket
    |> put_flash(:success, "Success")
    |> push_redirect(to: socket.assigns.return_to)}

In the parent Liveview.

<%= live_component @socket, YourComponentName,
....
 return_to: Routes.yourpath_path(@socket, :index) %>

By the way, I think handle_params should be paired with a live_patch or push_patch, not push_redirect.

1 Like

By the way, I think handle_params should be paired with a live_patch or push_patch, not push_redirect.

Good point! I’m going with this for now, although it does feel a little iffy:

Parent LiveView:

  def handle_params(params, url, socket) do
    # Make url relative
    uri = URI.parse(url)
    [_, relative_uri] = String.split(url, uri.authority, parts: 2)

    {:noreply,
     assign(socket,
       current_uri: relative_uri
     )}
  end
end

Child LiveComponent:

  def handle_event("my_event", _, socket) do
    # do something
    {:noreply,
      socket
        |> put_flash(:success, "Did something.")
        |> push_patch(to: socket.assigns.current_uri, replace: true)}

push_patch reuses the current parent LiveView, and replace: true doesn’t create a new browser history entry.