form_for and text_input macros

This commit is contained in:
Mitchell Hanberg 2019-05-10 15:06:03 -04:00
parent 083ff0682e
commit 06cbdd80ff
3 changed files with 110 additions and 6 deletions

View file

@ -25,7 +25,9 @@ defmodule Dsl.Html do
area br col embed hr img input keygen param source track wbr
]a
@doc false
def nonvoid_elements, do: @nonvoid_elements
@doc false
def void_elements, do: @void_elements
@doc """
@ -55,6 +57,7 @@ defmodule Dsl.Html do
quote do
import Kernel, except: [div: 2]
import HTML.Link, except: [link: 1, link: 2]
import HTML.Form, only: []
{:ok, var!(buff, Dsl.Html)} = Utils.start_buffer([])
@ -200,12 +203,59 @@ defmodule Dsl.Html do
end
end
end
@doc """
Generates an empty form tag.
See `Dsl.Html.form_for/4` for more details
"""
defmacro form_for(form_data, action) do
quote do
form_for(unquote_splicing([form_data, action]), [])
end
end
@doc """
Generates a form tag with a form builder and a block.
The form builder will be available inside the block through the `form` variable.
This is a wrapper around the `Phoenix.HTML.Form.form_for/4` function and accepts all of the same options.
## Example
```
htm do
form_for @conn, Routes.some_path(@conn, :create) do
text_input form, :name
end
end
# {:safe,
# "<form accept-charset=\"UTF-8\" action=\"/\" method=\"post\">
# <input name=\"_csrf_token\" type=\"hidden\" value=\"AS5qfX1gcns6eU56BlQgBlwCDgMlNgAAiJ0MR91Kh3v3bbCS5SKjuw==\">
# <input name=\"_utf8\" type=\"hidden\" value=\"✓\">
# <input id=\"name\" name=\"name\" type=\"text\">
# </form>"}
```
"""
defmacro form_for(form_data, action, opts \\ [], block) do
quote do
var!(form) = HTML.Form.form_for(unquote_splicing([form_data, action, opts]))
Utils.put_buffer(var!(buff, Dsl.Html), var!(form) |> HTML.Safe.to_iodata())
_ = unquote(block)
Utils.put_buffer(var!(buff, Dsl.Html), "</form>")
end
end
@doc """
Please see `Phoenix.HTML.Form.text_input/3` for details.
"""
defmacro text_input(form, field, opts \\ []) do
quote do
{:safe, input} = HTML.Form.text_input(unquote_splicing([form, field, opts]))
Utils.put_buffer(var!(buff, Dsl.Html), input)
end
end
end

View file

@ -13,7 +13,10 @@ defmodule Dsl.MixProject do
source_url: "https://github.com/mhanberg/cogent",
docs: [
main: "Dsl",
extras: ["README.md"]
extras: ["README.md"],
deps: [
phoenix_html: "https://hexdocs.pm/phoenix_html/"
]
],
dialyzer: [plt_add_apps: [:mix, :phoenix, :html_sanitize_ex]]
]
@ -35,7 +38,7 @@ defmodule Dsl.MixProject do
[
{:phoenix_html, "~> 2.13"},
{:ex_doc, "~> 0.0", only: [:dev], runtime: false},
{:html_sanitize_ex, "~> 1.3", only: [:dev], runtime: false},
{:html_sanitize_ex, "~> 1.3", only: [:dev, :test], runtime: false},
{:phoenix, "~> 1.4", optional: true},
{:plug, "~> 1.8", optional: true},
{:dialyxir, "~> 1.0.0-rc.6", only: [:dev], runtime: false}

View file

@ -399,4 +399,55 @@ defmodule Dsl.HtmlTest do
assert result == ~s{<div class="hi world"></div>}
end
end
describe "form_for" do
test "returns a form tag" do
conn = %Plug.Conn{}
action = "/"
{:safe, result} =
htm do
form_for(conn, action, [])
end
assert result =~ ~s{<form}
assert result =~ ~s{</form>}
end
test "can take a block" do
conn = %Plug.Conn{}
action = "/"
opts = []
{:safe, result} =
htm do
form_for conn, action, opts do
div()
end
end
assert result =~ ~s{<form}
assert result =~ ~s{<div></div>}
assert result =~ ~s{</form>}
end
test "can take a block that references the form" do
conn = %Plug.Conn{}
action = "/"
opts = []
{:safe, result} =
htm do
form_for conn, action, opts do
text_input(form, :bob)
end
end
assert result =~ ~s{<form}
assert result =~ ~s{<input}
assert result =~ ~s{type="text"}
assert result =~ ~s{name="bob"}
assert result =~ ~s{</form>}
end
end
end