diff --git a/lib/backpex/html/item_action.ex b/lib/backpex/html/item_action.ex
index 01a4f568f..cb0a9938b 100644
--- a/lib/backpex/html/item_action.ex
+++ b/lib/backpex/html/item_action.ex
@@ -36,7 +36,7 @@ defmodule Backpex.HTML.ItemAction do
id={:item_action_modal}
live_resource={@live_resource}
action_type={:item}
- {Map.drop(assigns, [:socket, :flash, :fields])}
+ {Map.drop(assigns, [:fields | Backpex.HTML.Resource.lv_reserved_assigns()])}
/>
diff --git a/lib/backpex/html/resource.ex b/lib/backpex/html/resource.ex
index 6a1d9ee51..48816e2fe 100644
--- a/lib/backpex/html/resource.ex
+++ b/lib/backpex/html/resource.ex
@@ -17,6 +17,16 @@ defmodule Backpex.HTML.Resource do
embed_templates("resource/*")
+ @doc """
+ Returns the list of assigns that `Phoenix.LiveView` reserves and that must be dropped
+ before spreading parent assigns into a child `Phoenix.LiveComponent`.
+
+ `Phoenix.Component.assign/3` rejects these keys with an `ArgumentError`. Centralizing
+ the list here ensures every spread site forwards the same safe subset of the parent's
+ assigns.
+ """
+ def lv_reserved_assigns, do: [:flash, :uploads, :streams, :socket, :myself]
+
@doc """
Renders a resource table.
"""
@@ -112,7 +122,7 @@ defmodule Backpex.HTML.Resource do
id={"resource_#{@name}_#{@primary_key}"}
module={@field_options.module}
type={@type}
- {Map.drop(assigns, [:socket, :flash, :myself, :uploads])}
+ {Map.drop(assigns, lv_reserved_assigns())}
/>
"""
end
@@ -148,7 +158,7 @@ defmodule Backpex.HTML.Resource do
id={@id}
module={@field_options.module}
type={@type}
- {Map.drop(assigns, [:socket, :flash, :myself, :uploads])}
+ {Map.drop(assigns, lv_reserved_assigns())}
/>
"""
end
@@ -183,7 +193,7 @@ defmodule Backpex.HTML.Resource do
module={@field_options.module}
lv_uploads={assigns[:uploads]}
type={@type}
- {Map.drop(assigns, [:socket, :flash, :myself, :uploads])}
+ {Map.drop(assigns, lv_reserved_assigns())}
/>
"""
end
diff --git a/lib/backpex/html/resource/resource_form_main.html.heex b/lib/backpex/html/resource/resource_form_main.html.heex
index 414e97df8..f82018822 100644
--- a/lib/backpex/html/resource/resource_form_main.html.heex
+++ b/lib/backpex/html/resource/resource_form_main.html.heex
@@ -3,6 +3,6 @@
module={Backpex.FormComponent}
id={:edit}
live_resource={@live_resource}
- {Map.drop(assigns, [:socket, :flash])}
+ {Map.drop(assigns, lv_reserved_assigns())}
/>
diff --git a/lib/backpex/html/resource/resource_index.html.heex b/lib/backpex/html/resource/resource_index.html.heex
index 1b776fa9a..be97f8dbb 100644
--- a/lib/backpex/html/resource/resource_index.html.heex
+++ b/lib/backpex/html/resource/resource_index.html.heex
@@ -12,7 +12,7 @@
id={:modal}
live_resource={@live_resource}
action_type={:resource}
- {Map.drop(assigns, [:socket, :flash, :fields])}
+ {Map.drop(assigns, [:fields | lv_reserved_assigns()])}
/>
diff --git a/test/backpex/html/resource_test.exs b/test/backpex/html/resource_test.exs
new file mode 100644
index 000000000..1d93dd288
--- /dev/null
+++ b/test/backpex/html/resource_test.exs
@@ -0,0 +1,24 @@
+defmodule Backpex.HTML.ResourceTest do
+ use ExUnit.Case, async: true
+
+ alias Backpex.HTML.Resource
+
+ describe "lv_reserved_assigns/0" do
+ test "includes every assign reserved by Phoenix.LiveView" do
+ reserved = Resource.lv_reserved_assigns()
+
+ for key <- [:flash, :uploads, :streams, :socket, :myself] do
+ assert key in reserved, "expected #{inspect(key)} in lv_reserved_assigns/0"
+ end
+ end
+
+ test "dropping the reserved set removes :streams from a parent-style assigns map" do
+ assigns = %{streams: %{example: :ref}, foo: 1, bar: 2}
+
+ result = Map.drop(assigns, Resource.lv_reserved_assigns())
+
+ refute Map.has_key?(result, :streams)
+ assert result == %{foo: 1, bar: 2}
+ end
+ end
+end