From b6d63e7908972dd4f0539e0daa9387ebdb701e37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Valim?= Date: Sun, 17 Nov 2024 19:16:05 +0100 Subject: [PATCH] Document and pass through option accordingly --- lib/phoenix_html/form.ex | 4 ++++ lib/phoenix_html/form_data.ex | 18 +++++++++--------- test/phoenix_html/form_test.exs | 11 ++++++++--- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/lib/phoenix_html/form.ex b/lib/phoenix_html/form.ex index 0699aeb..dbbda53 100644 --- a/lib/phoenix_html/form.ex +++ b/lib/phoenix_html/form.ex @@ -36,6 +36,10 @@ defmodule Phoenix.HTML.Form do * `:source` - the data structure that implements the form data protocol + * `:action` - The action that was taken against the form. This value can be + used to distinguish between different operations such as the user typing + into a form for validation, or submitting a form for a database insert. + * `:impl` - the module with the form data protocol implementation. This is used to avoid multiple protocol dispatches. diff --git a/lib/phoenix_html/form_data.ex b/lib/phoenix_html/form_data.ex index 0efc546..0a67a51 100644 --- a/lib/phoenix_html/form_data.ex +++ b/lib/phoenix_html/form_data.ex @@ -78,8 +78,8 @@ defprotocol Phoenix.HTML.FormData do end defimpl Phoenix.HTML.FormData, for: Map do - def to_form(conn_or_atom_or_map, opts) do - {name, params, opts} = name_params_and_opts(conn_or_atom_or_map, opts) + def to_form(map, opts) do + {name, params, opts} = name_params_and_opts(map, opts) {errors, opts} = Keyword.pop(opts, :errors, []) {action, opts} = Keyword.pop(opts, :action, nil) id = Keyword.get(opts, :id) || name @@ -89,7 +89,7 @@ defimpl Phoenix.HTML.FormData, for: Map do end %Phoenix.HTML.Form{ - source: conn_or_atom_or_map, + source: map, impl: __MODULE__, id: id, name: name, @@ -115,14 +115,14 @@ defimpl Phoenix.HTML.FormData, for: Map do end end - def to_form(conn_or_atom_or_map, form, field, opts) when is_atom(field) or is_binary(field) do + def to_form(map, form, field, opts) when is_atom(field) or is_binary(field) do {default, opts} = Keyword.pop(opts, :default, %{}) {prepend, opts} = Keyword.pop(opts, :prepend, []) {append, opts} = Keyword.pop(opts, :append, []) {name, opts} = Keyword.pop(opts, :as) {id, opts} = Keyword.pop(opts, :id) {hidden, opts} = Keyword.pop(opts, :hidden, []) - {action, opts} = Keyword.pop(opts, :action) + {action, opts} = Keyword.pop(opts, :action, form.action) id = to_string(id || form.id <> "_#{field}") name = to_string(name || form.name <> "[#{field}]") @@ -133,7 +133,7 @@ defimpl Phoenix.HTML.FormData, for: Map do is_map(default) -> [ %Phoenix.HTML.Form{ - source: conn_or_atom_or_map, + source: map, impl: __MODULE__, id: id, name: name, @@ -160,7 +160,7 @@ defimpl Phoenix.HTML.FormData, for: Map do index_string = Integer.to_string(index) %Phoenix.HTML.Form{ - source: conn_or_atom_or_map, + source: map, impl: __MODULE__, index: index, action: action, @@ -175,7 +175,7 @@ defimpl Phoenix.HTML.FormData, for: Map do end end - def input_value(_conn_or_atom_or_map, %{data: data, params: params}, field) + def input_value(_map, %{data: data, params: params}, field) when is_atom(field) or is_binary(field) do key = field_to_string(field) @@ -185,7 +185,7 @@ defimpl Phoenix.HTML.FormData, for: Map do end end - def input_validations(_conn_or_atom_or_map, _form, _field), do: [] + def input_validations(_map, _form, _field), do: [] # Normalize field name to string version defp field_to_string(field) when is_atom(field), do: Atom.to_string(field) diff --git a/test/phoenix_html/form_test.exs b/test/phoenix_html/form_test.exs index 523b76f..54fb0d8 100644 --- a/test/phoenix_html/form_test.exs +++ b/test/phoenix_html/form_test.exs @@ -314,7 +314,7 @@ defmodule Phoenix.HTML.FormTest do } } - form = Phoenix.HTML.FormData.to_form(map, as: "search") + form = Phoenix.HTML.FormData.to_form(map, as: "search", action: :validate) Phoenix.HTML.FormData.to_form(map, form, field, opts) end @@ -329,6 +329,7 @@ defmodule Phoenix.HTML.FormTest do id: "search_unknown_year", name: "search[unknown][year]", field: :year, + form: %{action: :validate}, value: nil } = f[:year] end @@ -340,6 +341,7 @@ defmodule Phoenix.HTML.FormTest do id: "search_date_year", name: "search[date][year]", field: :year, + form: %{action: :validate}, value: "2020" } = f[:year] end @@ -351,6 +353,7 @@ defmodule Phoenix.HTML.FormTest do id: "search_unknown_year", name: "search[unknown][year]", field: :year, + form: %{action: :validate}, value: 2015 } = f[:year] end @@ -362,17 +365,19 @@ defmodule Phoenix.HTML.FormTest do id: "search_date_year", name: "search[date][year]", field: :year, + form: %{action: :validate}, value: "2020" } = f[:year] end - test "one: with custom name and id" do - [f] = nested_form(:date, as: :foo, id: :bar) + test "one: with custom name, id, and action" do + [f] = nested_form(:date, as: :foo, id: :bar, action: :another) assert %Phoenix.HTML.FormField{ id: "bar_year", name: "foo[year]", field: :year, + form: %{action: :another}, value: "2020" } = f[:year] end