diff --git a/lib/ex_cell/base.ex b/lib/ex_cell/base.ex
index ccbb3a2..60708d5 100644
--- a/lib/ex_cell/base.ex
+++ b/lib/ex_cell/base.ex
@@ -4,6 +4,7 @@ defmodule ExCell.Base do
defmacro __using__(opts \\ []) do
quote do
import ExCell.View
+ import ExCell.LiveView
@adapter unquote(opts[:adapter])
@namespace unquote(opts[:namespace])
diff --git a/lib/ex_cell/live_view.ex b/lib/ex_cell/live_view.ex
new file mode 100644
index 0000000..e44d953
--- /dev/null
+++ b/lib/ex_cell/live_view.ex
@@ -0,0 +1,64 @@
+defmodule ExCell.LiveView do
+ @moduledoc """
+ Cell helpers used to render the live view cells in both Views and Cells
+ """
+ @view_adapter ExCell.config(:view_adapter, Phoenix.LiveView.Helpers)
+
+ @doc """
+ Renders a cell in the view.
+
+ ### Examples
+ iex(0)> safe_to_string(AppWeb.AvatarView.live_cell(AvatarLiveCell, socket))
+ "
"
+ """
+ def live_cell(cell, conn_or_socket) do
+ render_cell(cell, conn_or_socket, [])
+ end
+
+ @doc """
+ Renders a cell in the view with children.
+
+ ### Examples
+ iex(0)> safe_to_string(AppWeb.AvatarView.live_cell(AvatarLiveCell, do: "Foo"))
+ "
Foo
"
+ """
+ def live_cell(cell, conn_or_socket, do: children) do
+ render_cell(cell, conn_or_socket, children: children)
+ end
+
+ @doc """
+ Renders a cell in the view with assigns.
+
+ ### Examples
+ iex(0)> safe_to_string(AppWeb.AvatarView.live_cell(AvatarLiveCell, user: %User{name: "Bar"}))
+ "
Bar
"
+ """
+ def live_cell(cell, conn_or_socket, assigns) when is_list(assigns) do
+ render_cell(cell, conn_or_socket, assigns)
+ end
+
+ @doc """
+ Renders a cell in the view with children without a block.
+
+ ### Examples
+ iex(0)> safe_to_string(AppWeb.AvatarView.live_cell(AvatarLiveCell, "Hello"))
+ "
Hello
"
+ """
+ def live_cell(cell, conn_or_socket, children) do
+ render_cell(cell, conn_or_socket, children: children)
+ end
+
+ def live_cell(cell, conn_or_socket, assigns, do: children) when is_list(assigns) do
+ render_cell(cell, conn_or_socket, [children: children] ++ assigns)
+ end
+
+ def live_cell(cell, conn_or_socket, children, assigns) when is_list(assigns) do
+ render_cell(cell, conn_or_socket, [children: children] ++ assigns)
+ end
+
+ defp render_cell(cell, conn_or_socket, assigns) do
+ assigns = Map.new(assigns)
+
+ @view_adapter.live_render(conn_or_socket, cell, session: %{"assigns" => assigns})
+ end
+end
diff --git a/mix.exs b/mix.exs
index 3b181e5..1910a93 100644
--- a/mix.exs
+++ b/mix.exs
@@ -51,8 +51,9 @@ defmodule ExCell.Mixfile do
{:ex_doc, ">= 0.0.0", only: [:dev, :test]},
{:excoveralls, "~> 0.7", only: :test},
{:mix_test_watch, "~> 1.0", only: :dev, runtime: false},
- {:phoenix_html, "~> 2.10"},
- {:phoenix, "~> 1.4.0", optional: true},
+ {:phoenix_html, "~> 2.14"},
+ {:phoenix_live_view, "~> 0.13.3"},
+ {:phoenix, "~> 1.4.17", optional: true},
{:jason, "~> 1.1"},
{:elixir_uuid, "~> 1.2"}
]
diff --git a/mix.lock b/mix.lock
index 5d043ac..922a087 100644
--- a/mix.lock
+++ b/mix.lock
@@ -10,7 +10,7 @@
"file_system": {:hex, :file_system, "0.2.8", "f632bd287927a1eed2b718f22af727c5aeaccc9a98d8c2bd7bff709e851dc986", [:mix], [], "hexpm", "97a3b6f8d63ef53bd0113070102db2ce05352ecf0d25390eb8d747c2bde98bca"},
"hackney": {:hex, :hackney, "1.15.2", "07e33c794f8f8964ee86cebec1a8ed88db5070e52e904b8f12209773c1036085", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.5", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm", "e0100f8ef7d1124222c11ad362c857d3df7cb5f4204054f9f0f4a728666591fc"},
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "4bdd305eb64e18b0273864920695cb18d7a2021f31a11b9c5fbcd9a253f936e2"},
- "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fdf843bca858203ae1de16da2ee206f53416bbda5dc8c9e78f43243de4bc3afe"},
+ "jason": {:hex, :jason, "1.2.1", "12b22825e22f468c02eb3e4b9985f3d0cb8dc40b9bd704730efa11abd2708c44", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
"makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "a10c6eb62cca416019663129699769f0c2ccf39428b3bb3c0cb38c718a0c186d"},
"makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "d4b316c7222a85bbaa2fd7c6e90e37e953257ad196dc229505137c5e505e9eff"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
@@ -19,10 +19,11 @@
"mix_test_watch": {:hex, :mix_test_watch, "1.0.2", "34900184cbbbc6b6ed616ed3a8ea9b791f9fd2088419352a6d3200525637f785", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "47ac558d8b06f684773972c6d04fcc15590abdb97aeb7666da19fcbfdc441a07"},
"nimble_parsec": {:hex, :nimble_parsec, "0.5.3", "def21c10a9ed70ce22754fdeea0810dafd53c2db3219a0cd54cf5526377af1c6", [], [], "hexpm", "589b5af56f4afca65217a1f3eb3fee7e79b09c40c742fddc1c312b3ac0b3399f"},
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm", "17ef63abde837ad30680ea7f857dd9e7ced9476cdd7b0394432af4bfc241b960"},
- "phoenix": {:hex, :phoenix, "1.4.13", "67271ad69b51f3719354604f4a3f968f83aa61c19199343656c9caee057ff3b8", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ab765a0feddb81fc62e2116c827b5f068df85159c162bee760745276ad7ddc1b"},
- "phoenix_html": {:hex, :phoenix_html, "2.13.3", "850e292ff6e204257f5f9c4c54a8cb1f6fbc16ed53d360c2b780a3d0ba333867", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "8b01b3d6d39731ab18aa548d928b5796166d2500755f553725cfe967bafba7d9"},
+ "phoenix": {:hex, :phoenix, "1.4.17", "1b1bd4cff7cfc87c94deaa7d60dd8c22e04368ab95499483c50640ef3bd838d8", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.8.1 or ~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
+ "phoenix_html": {:hex, :phoenix_html, "2.14.2", "b8a3899a72050f3f48a36430da507dd99caf0ac2d06c77529b1646964f3d563e", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
+ "phoenix_live_view": {:hex, :phoenix_live_view, "0.13.3", "2186c55cc7c54ca45b97c6f28cfd267d1c61b5f205f3c83533704cd991bdfdec", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.4.17 or ~> 1.5.2", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm"},
"phoenix_pubsub": {:hex, :phoenix_pubsub, "1.1.2", "496c303bdf1b2e98a9d26e89af5bba3ab487ba3a3735f74bf1f4064d2a845a3e", [:mix], [], "hexpm", "1f13f9f0f3e769a667a6b6828d29dec37497a082d195cc52dbef401a9b69bf38"},
- "plug": {:hex, :plug, "1.9.0", "8d7c4e26962283ff9f8f3347bd73838e2413fbc38b7bb5467d5924f68f3a5a4a", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "9902eda2c52ada2a096434682e99a2493f5d06a94d6ac6bcfff9805f952350f1"},
+ "plug": {:hex, :plug, "1.10.3", "c9cebe917637d8db0e759039cc106adca069874e1a9034fd6e3fdd427fd3c283", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm"},
"plug_crypto": {:hex, :plug_crypto, "1.1.2", "bdd187572cc26dbd95b87136290425f2b580a116d3fb1f564216918c9730d227", [:mix], [], "hexpm", "6b8b608f895b6ffcfad49c37c7883e8df98ae19c6a28113b02aa1e9c5b22d6b5"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm", "13104d7897e38ed7f044c4de953a6c28597d1c952075eb2e328bc6d6f2bfc496"},
"telemetry": {:hex, :telemetry, "0.4.1", "ae2718484892448a24470e6aa341bc847c3277bfb8d4e9289f7474d752c09c7f", [:rebar3], [], "hexpm", "4738382e36a0a9a2b6e25d67c960e40e1a2c95560b9f936d8e29de8cd858480f"},
diff --git a/test/ex_cell/live_view_test.exs b/test/ex_cell/live_view_test.exs
new file mode 100644
index 0000000..055e339
--- /dev/null
+++ b/test/ex_cell/live_view_test.exs
@@ -0,0 +1,48 @@
+defmodule ExCell.LiveViewTest do
+ use ExCell.ConnCase
+ alias ExCell.LiveView
+
+ test "live_cell/2 with ExCell", %{conn: conn} do
+ assert LiveView.live_cell(:mock_cell, conn) === [conn, :mock_cell, [session: %{assigns: %{}}]]
+ end
+
+ test "live_cell/3 with assigns", %{conn: conn} do
+ assert LiveView.live_cell(:mock_cell, conn, foo: "bar") === [
+ conn,
+ :mock_cell,
+ [session: %{assigns: %{foo: "bar"}}]
+ ]
+ end
+
+ test "live_cell/3 with do block", %{conn: conn} do
+ assert LiveView.live_cell(:mock_cell, conn, do: "yes") === [
+ conn,
+ :mock_cell,
+ [session: %{assigns: %{children: "yes"}}]
+ ]
+ end
+
+ test "live_cell/3 with children", %{conn: conn} do
+ assert LiveView.live_cell(:mock_cell, conn, "yes") === [
+ conn,
+ :mock_cell,
+ [session: %{assigns: %{children: "yes"}}]
+ ]
+ end
+
+ test "live_cell/3 with assign and do block", %{conn: conn} do
+ assert LiveView.live_cell(:mock_cell, conn, [foo: "bar"], do: "yes") === [
+ conn,
+ :mock_cell,
+ [session: %{assigns: %{children: "yes", foo: "bar"}}]
+ ]
+ end
+
+ test "live_cell/3 with children and assign", %{conn: conn} do
+ assert LiveView.live_cell(:mock_cell, conn, "yes", foo: "bar") === [
+ conn,
+ :mock_cell,
+ [session: %{assigns: %{children: "yes", foo: "bar"}}]
+ ]
+ end
+end
diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex
new file mode 100644
index 0000000..062bb2e
--- /dev/null
+++ b/test/support/conn_case.ex
@@ -0,0 +1,28 @@
+defmodule ExCell.ConnCase do
+ @moduledoc """
+ This module defines the test case to be used by
+ tests that require setting up a connection.
+
+ Such tests rely on `Phoenix.ConnTest` and also
+ import other functionality to make it easier
+ to build common data structures and query the data layer.
+
+ Finally, if the test case interacts with the database,
+ it cannot be async. For this reason, every test runs
+ inside a transaction which is reset at the beginning
+ of the test unless the test case is marked as async.
+ """
+
+ use ExUnit.CaseTemplate
+
+ using do
+ quote do
+ # Import conveniences for testing with connections
+ use Phoenix.ConnTest
+ end
+ end
+
+ setup _tags do
+ {:ok, conn: Phoenix.ConnTest.build_conn()}
+ end
+end
diff --git a/test/support/mock_view_adapter.ex b/test/support/mock_view_adapter.ex
index 4a718a7..6690f3f 100644
--- a/test/support/mock_view_adapter.ex
+++ b/test/support/mock_view_adapter.ex
@@ -2,4 +2,5 @@ defmodule ExCell.MockViewAdapter do
@moduledoc false
def render(cell, template, args), do: [cell, template, args]
def render_to_string(cell, template, args), do: [cell, template, args]
+ def live_render(conn, cell, args), do: [conn, cell, args]
end