Last active
August 29, 2015 14:15
-
-
Save smpallen99/63a85ff2225c6b9c46e1 to your computer and use it in GitHub Desktop.
Elixir form helpers prototype
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule ExForm do | |
@moduledoc """ | |
Prototype for a helpers to generate html forms. Usable with Phoenix. | |
""" | |
@doc """ | |
Generates a html form. | |
## Syntax: | |
1. pass model name atom and use input_field | |
form_for :my_model, [url: "/"], fn(f) -> | |
f | |
|> input_field(:name, my_model.name) | |
|> submit("save") | |
end | |
2. pass model struct and use input | |
form_for my_model, [url: "/"], fn(f) -> | |
f | |
|> input(:name) | |
|> submit("save") | |
end | |
""" | |
def form_for(name_or_mode, opts \\ [], fun \\ nil) | |
def form_for(%{__struct__: model_name} = model, opts, fun) do | |
_form_for(model, underscore(model_name), opts, fun) | |
end | |
def form_for(model_name, opts, fun) do | |
_form_for(nil, model_name, opts, fun) | |
end | |
defp _form_for(model, model_name, opts, fun) do | |
method = Keyword.get(opts, :method, "post") | |
url = Keyword.get(opts, :url, "/") | |
charset = Keyword.get(opts, :charset, "UTF-8") | |
class = case Keyword.get(opts, :class, nil) do | |
nil -> " " | |
other -> " class='#{other}' " | |
end | |
data = "<form method='#{method}' accept-charset='#{charset}' " <> | |
"id='new_#{model_name}'#{class}" <> | |
"action='#{url}'>\r\n" | |
form_data = %{model: model, model_name: model_name, data: data, type: :form} | |
case fun do | |
nil -> form_data | |
other -> | |
other.(form_data) | |
|> render_form_data | |
end | |
end | |
@doc """ | |
Generate an input field | |
Generates an input field for the provided form data that includes a the given | |
model data. | |
## Syntax | |
input(form_data, :name, class: "one two", style: "some style") | |
""" | |
def input(%{model: model} = form_data, name, type \\ "text", opts \\ []) when model != nil do | |
input_field(form_data, name, Map.get(model, name, nil), type, opts) | |
end | |
def input_field(%{data: data, model_name: model_name} = form_data, name, value, type \\ "text", opts \\ []) do | |
data = data <> "<input type='#{type}' id='#{model_name}_#{name}' name='#{model_name}[#{name}]' value='#{value}' />\r\n" | |
Map.put form_data, :data, data | |
end | |
@doc """ | |
Generate a hidden input field, given form_data containing a the model | |
## Syntax | |
hidden(form_data, :group_id) | |
""" | |
def hidden(form_data, name, opts \\ []), do: input(form_data, name, "hidden", opts) | |
@doc """ | |
Generate a hidden field for form_data that does not include a model | |
## Syntax | |
hidden_field(form_data, :group_id, my_model.group_id) | |
""" | |
def hidden_field(form_data, name, value, opts \\ []), do: input_field(form_data, name, value, "hidden", opts) | |
@doc """ | |
Generate a submit button | |
""" | |
def submit(%{data: data} = form_data, value \\ "submit", _opts \\ []) do | |
data = data <> "<input type='submit' name='commit' value='#{value}' />\r\n" | |
Map.put form_data, :data, data | |
end | |
@doc """ | |
Generate the underscored model name, given the model Atom | |
## Syntax | |
iex> underscore(MyProject.MyModel) | |
:my_model | |
""" | |
def underscore(module) do | |
module | |
|> Atom.to_string | |
|> String.split(".") | |
|> List.last | |
|> Mix.Utils.underscore | |
end | |
defp render_form_data(%{type: :form, data: data}) do | |
Phoenix.HTML.safe data <> "</form>\r\n" | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule MyProject.View do | |
# ... | |
@doc """ | |
Generate html for a link | |
## Syntax | |
iex> link_to("click me", "/something", class: "link btn", style: "some styling") | |
{:safe, "<a href='/something' class='link btn' style='some styling'>click me</a>"} | |
""" | |
def link_to(name, path, opts \\[]) do | |
attributes = Keyword.delete(opts, :remote) | |
|> Enum.reduce("", fn({k,v}, acc) -> acc <> "#{k}='#{v}' " end) | |
"<a href='#{path}' #{attributes}>#{name}</a>" | |
|> Phoenix.HTML.safe | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment