Skip to content
Permalink
Browse files

Add options for html_element and pass others through to html element

  • Loading branch information
geolessel committed Mar 28, 2018
1 parent 47f7890 commit 7046c618276168c51c78b9551aeac6d67e5931a5
Showing with 55 additions and 10 deletions.
  1. +31 −4 lib/react_phoenix/client_side.ex
  2. +24 −6 test/react_phoenix/client_side_test.exs
@@ -76,14 +76,41 @@ defmodule ReactPhoenix.ClientSide do
The resulting `<div>` tag is formatted specifically for the included javascript
helper to then turn into your named React component and then pass in the props specified.
## Options
You can pass a Keyword list of options that controls the rendering of the final html element
that the react component will be rendered into.
* `target_id` - If you have a rendered html element already on your page with a unique `id`
attribute, this will render your react component into _that_ already-existing element
instead of creating one of its own. The default is an empty string, which will cause it
to render into its own created element.
* `html_element` - By default, `ReactPhoenix.ClientSide.react_component/3` will create a
`div` for output in your template. If you'd rather use a different element (`span`, `ul`, etc.),
you can specify it here as an atom (e.g. `:span`, `:ul`, etc.).
Anything else you pass in will be further passed directly to the html element it
creates as attributes. This allows you more control over the element. Some useful examples
of what you would specify are `class`, `id`, `style`, etc.
"""
@spec react_component(name :: String.t(), props :: map, opts :: [target_id: String.t()]) ::
@spec react_component(name :: String.t(), props :: map, opts :: list()) ::
Phoenix.HTML.safe()
def react_component(name, props, opts) when is_map(props) do
props = Jason.encode!(props)

content_tag(:div, "", [
{:data, [react_class: name, react_props: props, react_target_id: opts[:target_id]]}
])
{html_element, opts} = Keyword.pop(opts, :html_element, :div)
{target_id, opts} = Keyword.pop(opts, :target_id, "")

content_tag(
html_element,
"",
Keyword.merge(
[
{:data, [react_class: name, react_props: props, react_target_id: target_id]}
],
opts
)
)
end
end
@@ -3,21 +3,21 @@ defmodule ReactPhoenix.ClientSideTest do
doctest ReactPhoenix.ClientSide
import ReactPhoenix.ClientSide

test "react_component returns a safe tuple" do
test "react_component/1 returns a safe tuple" do
assert {:safe, _} = react_component("test")
end

test "react_component returns a renderable div" do
test "react_component/1 returns a renderable div" do
html = Phoenix.HTML.safe_to_string(react_component("test"))
assert String.match?(html, ~r|^<div.*></div>$|)
end

test "react_component returns a renderable div with data-react-class containing component name" do
test "react_component/1 returns a renderable div with data-react-class containing component name" do
html = Phoenix.HTML.safe_to_string(react_component("test"))
assert String.match?(html, ~r|data-react-class="test"|)
end

test "react_component returns a renderable div with data-react-props containing props list" do
test "react_component/2 returns a renderable div with data-react-props containing props list" do
html = Phoenix.HTML.safe_to_string(react_component("test", my: "props"))

expected =
@@ -26,7 +26,7 @@ defmodule ReactPhoenix.ClientSideTest do
assert html == expected
end

test "react_component returns a renderable div with data-react-props containing props map" do
test "react_component/2 returns a renderable div with data-react-props containing props map" do
html = Phoenix.HTML.safe_to_string(react_component("test", %{my: "props"}))

expected =
@@ -35,12 +35,30 @@ defmodule ReactPhoenix.ClientSideTest do
assert html == expected
end

test "react_component accepts a target div option" do
test "react_component/3 accepts a target div option" do
html = Phoenix.HTML.safe_to_string(react_component("test", %{}, target_id: "test-id"))

expected =
"<div data-react-class=\"test\" data-react-props=\"{}\" data-react-target-id=\"test-id\"></div>"

assert html == expected
end

test "react_component/3 accepts a html_element option" do
html = Phoenix.HTML.safe_to_string(react_component("test", %{}, html_element: :span))

expected =
"<span data-react-class=\"test\" data-react-props=\"{}\" data-react-target-id=\"\"></span>"

assert html == expected
end

test "react_component/3 passes on extra options to the html element" do
html = Phoenix.HTML.safe_to_string(react_component("test", %{}, class: "row", id: "content"))

expected =
"<div class=\"row\" data-react-class=\"test\" data-react-props=\"{}\" data-react-target-id=\"\" id=\"content\"></div>"

assert html == expected
end
end

0 comments on commit 7046c61

Please sign in to comment.
You can’t perform that action at this time.