Skip to content

Commit

Permalink
Push pending events before redirecting
Browse files Browse the repository at this point in the history
Previously, there was no way to handle both `push_event` and
`push_redirect` occuring in the same callback. The redirect would
prevent the events from being sent. This commit checks the diff for any
new events, and if they exist, sends them over the channel.
  • Loading branch information
Gazler committed Nov 16, 2023
1 parent 0fbabeb commit d99b1ee
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
9 changes: 9 additions & 0 deletions lib/phoenix_live_view/channel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -799,20 +799,23 @@ defmodule Phoenix.LiveView.Channel do
|> Map.put(:to, to)

new_state
|> push_pending_events_on_redirect(new_socket)
|> push_redirect(opts, ref)
|> stop_shutdown_redirect(:redirect, opts)

{:redirect, %{to: _to} = opts} ->
opts = copy_flash(new_state, flash, opts)

new_state
|> push_pending_events_on_redirect(new_socket)
|> push_redirect(opts, ref)
|> stop_shutdown_redirect(:redirect, opts)

{:live, :redirect, %{to: _to} = opts} ->
opts = copy_flash(new_state, flash, opts)

new_state
|> push_pending_events_on_redirect(new_socket)
|> push_live_redirect(opts, ref, pending_diff_ack)
|> stop_shutdown_redirect(:live_redirect, opts)

Expand All @@ -837,6 +840,12 @@ defmodule Phoenix.LiveView.Channel do
end
end

defp push_pending_events_on_redirect(state, socket) do
{:diff, diff, _new_state} = render_diff(state, socket, false)
if events = Map.get(diff, :e), do: push(state, "diff", %{:e => events})
state
end

defp patch_params_and_action!(socket, %{to: to}) do
destructure [path, query], :binary.split(to, ["?", "#"], [:global])
to = %{socket.host_uri | path: path, query: query}
Expand Down
23 changes: 23 additions & 0 deletions test/phoenix_live_view/integrations/event_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,29 @@ defmodule Phoenix.LiveView.EventTest do
assert render(view) =~ "count: 123"
end

test "supports events with redirects", %{conn: conn} do
{:ok, view, _html} = live(conn, "/events")

GenServer.call(
view.pid,
{:run,
fn socket ->
new_socket =
socket
|> Component.assign(count: 123)
|> LiveView.push_event("my-event", %{one: 1})
|> LiveView.push_event("my-event", %{one: 2})
|> LiveView.push_redirect(to: "/events")

{:reply, :ok, new_socket}
end}
)

assert_push_event(view, "my-event", %{one: 1})
assert_push_event(view, "my-event", %{one: 2})
assert_redirected(view, "/events")
end

test "sends updates with no assigns diff", %{conn: conn} do
{:ok, view, _html} = live(conn, "/events")

Expand Down

0 comments on commit d99b1ee

Please sign in to comment.