Repository: phoenixframework/phoenix_html
Pull request #184 (2017-11-07 22:03:07)

No longer require the :as option.
Sometimes users need a way to create a
form that does not wrap params inside a
named param. This commit removes the
:as requirement. Forms without the :as option
will no longer have an id generated and the form
inputs will also forgo automatic id generation.

benwilson512: If I do:

```
<%= form_for @conn, session_path(@conn, :create), [as: :foo], fn f -> %>
```

And then try to render the form (not submit it, just render) I get:

```
Request: GET /admin/session/new
** (exit) an exception was raised:
    ** (BadMapError) expected a map, got: nil
        (stdlib) :maps.find("email", nil)
        (phoenix_html) lib/phoenix_html/form_data.ex:123: Phoenix.HTML.FormData.Plug.Conn.input_value/3
        (phoenix_html) lib/phoenix_html/form.ex:307: Phoenix.HTML.Form.input_value/2
        (phoenix_html) lib/phoenix_html/form.ex:528: Phoenix.HTML.Form.generic_input/4
        (plate_slate) lib/plate_slate_web/templates/session/new.html.eex:6: anonymous fn/1 in PlateSlateWeb.SessionView."new.html"/1
        (phoenix_html) lib/phoenix_html/form.ex:253: Phoenix.HTML.Form.form_for/4
        (plate_slate) lib/plate_slate_web/templates/session/new.html.eex:3: PlateSlateWeb.SessionView."new.html"/1
```
chrismccord: @benwilson512 I pushed a new commit like 3 minutes ago that should cover this :)

Can you try again and report back?
benwilson512: Oops! Totally fixed now :)

Patch:
diff --git a/lib/phoenix_html/form.ex b/lib/phoenix_html/form.ex
index 6858fcd..34735dd 100644
--- a/lib/phoenix_html/form.ex
+++ b/lib/phoenix_html/form.ex
@@ -325,6 +325,8 @@ defmodule Phoenix.HTML.Form do
   The form should either be a `Phoenix.HTML.Form` emitted
   by `form_for` or an atom.
   """
+  def input_id(%{id: nil}, _field),
+    do: nil
   def input_id(%{id: id}, field),
     do: "#{id}_#{field}"
   def input_id(name, field) when is_atom(name),
@@ -336,6 +338,8 @@ defmodule Phoenix.HTML.Form do
   The form should either be a `Phoenix.HTML.Form` emitted
   by `form_for` or an atom.
   """
+  def input_name(%{name: nil}, field),
+    do: field
   def input_name(%{name: name}, field),
     do: "#{name}[#{field}]"
   def input_name(name, field) when is_atom(name),
diff --git a/lib/phoenix_html/form_data.ex b/lib/phoenix_html/form_data.ex
index 1c120d3..1858da5 100644
--- a/lib/phoenix_html/form_data.ex
+++ b/lib/phoenix_html/form_data.ex
@@ -49,15 +49,22 @@ end
 
 defimpl Phoenix.HTML.FormData, for: Plug.Conn do
   def to_form(conn, opts) do
-    {name, opts} = Keyword.pop(opts, :as)
-    name = to_string(name || warn_name(opts) || no_name_error!())
+    {name, params, opts} =
+      case Keyword.pop(opts, :as) do
+        {nil, opts} ->
+          {nil, conn.params, opts}
+
+        {name, opts} ->
+          name = to_string(name || warn_name(opts))
+          {name, Map.get(conn.params, name) || %{}, opts}
+      end
 
     %Phoenix.HTML.Form{
       source: conn,
       impl: __MODULE__,
       id: name,
       name: name,
-      params: Map.get(conn.params, name) || %{},
+      params: params,
       options: opts,
       data: %{}
     }
@@ -124,11 +131,6 @@ defimpl Phoenix.HTML.FormData, for: Plug.Conn do
   def input_type(_conn, _form, _field), do: :text_input
   def input_validations(_conn, _form, _field), do: []
 
-  defp no_name_error! do
-    raise ArgumentError, "form_for/4 expects [as: NAME] to be given as option " <>
-                         "when used with @conn"
-  end
-
   defp warn_name(opts) do
     if name = Keyword.get(opts, :name) do
       IO.write :stderr, "the :name option in form_for/inputs_for is deprecated, " <>


Test patch:
diff --git a/test/phoenix_html/form_test.exs b/test/phoenix_html/form_test.exs
index 1899121..c10c85d 100644
--- a/test/phoenix_html/form_test.exs
+++ b/test/phoenix_html/form_test.exs
@@ -79,6 +79,14 @@ defmodule Phoenix.HTML.FormTest do
     assert form =~ "<form"
   end
 
+  test "form_for/3 with no name" do
+    form = safe_to_string form_for(conn(), "/", fn f ->
+      text_input(f, :key)
+    end)
+
+    assert form =~ ~s(<input name="key" type="text">)
+  end
+
   ## text_input/3
 
   test "text_input/3" do