diff --git a/lib/phoenix_html/form.ex b/lib/phoenix_html/form.ex
index 794252d..67e8c8b 100644
--- a/lib/phoenix_html/form.ex
+++ b/lib/phoenix_html/form.ex
@@ -64,6 +64,7 @@ defmodule Phoenix.HTML.Form do
id: nil,
name: nil,
data: nil,
+ action: nil,
hidden: [],
params: %{},
errors: [],
@@ -74,6 +75,7 @@ defmodule Phoenix.HTML.Form do
source: Phoenix.HTML.FormData.t(),
name: String.t(),
data: %{field => term},
+ action: atom(),
params: %{binary => term},
hidden: Keyword.t(),
options: Keyword.t(),
@@ -191,18 +193,32 @@ defmodule Phoenix.HTML.Form do
@doc """
Receives two forms structs and checks if the given field changed.
- The field will have changed if either its associated value or errors
- changed. This is mostly used for optimization engines as an extension
- of the `Access` behaviour.
+ The field will have changed if either its associated value, errors,
+ action, or implementation changed. This is mostly used for optimization
+ engines as an extension of the `Access` behaviour.
"""
@spec input_changed?(t, t, field()) :: boolean()
def input_changed?(
- %Form{impl: impl1, id: id1, name: name1, errors: errors1, source: source1} = form1,
- %Form{impl: impl2, id: id2, name: name2, errors: errors2, source: source2} = form2,
+ %Form{
+ impl: impl1,
+ id: id1,
+ name: name1,
+ errors: errors1,
+ source: source1,
+ action: action1
+ } = form1,
+ %Form{
+ impl: impl2,
+ id: id2,
+ name: name2,
+ errors: errors2,
+ source: source2,
+ action: action2
+ } = form2,
field
)
when is_atom(field) or is_binary(field) do
- impl1 != impl2 or id1 != id2 or name1 != name2 or
+ impl1 != impl2 or id1 != id2 or name1 != name2 or action1 != action2 or
field_errors(errors1, field) != field_errors(errors2, field) or
impl1.input_value(source1, form1, field) != impl2.input_value(source2, form2, field)
end
diff --git a/lib/phoenix_html/form_data.ex b/lib/phoenix_html/form_data.ex
index 02eec75..0efc546 100644
--- a/lib/phoenix_html/form_data.ex
+++ b/lib/phoenix_html/form_data.ex
@@ -56,6 +56,8 @@ defprotocol Phoenix.HTML.FormData do
applies if the field value is a list and no parameters were
sent through the form.
+ * `:action` - The user defined action being taken by the form, such
+ as `:validate`, `:save`, etc.
"""
@spec to_form(t, Phoenix.HTML.Form.t(), Phoenix.HTML.Form.field(), Keyword.t()) ::
[Phoenix.HTML.Form.t()]
@@ -79,6 +81,7 @@ 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)
{errors, opts} = Keyword.pop(opts, :errors, [])
+ {action, opts} = Keyword.pop(opts, :action, nil)
id = Keyword.get(opts, :id) || name
unless is_binary(id) or is_nil(id) do
@@ -93,6 +96,7 @@ defimpl Phoenix.HTML.FormData, for: Map do
params: params,
data: %{},
errors: errors,
+ action: action,
options: opts
}
end
@@ -118,6 +122,7 @@ defimpl Phoenix.HTML.FormData, for: Map do
{name, opts} = Keyword.pop(opts, :as)
{id, opts} = Keyword.pop(opts, :id)
{hidden, opts} = Keyword.pop(opts, :hidden, [])
+ {action, opts} = Keyword.pop(opts, :action)
id = to_string(id || form.id <> "_#{field}")
name = to_string(name || form.name <> "[#{field}]")
@@ -133,6 +138,7 @@ defimpl Phoenix.HTML.FormData, for: Map do
id: id,
name: name,
data: default,
+ action: action,
params: params || %{},
hidden: hidden,
options: opts
@@ -157,6 +163,7 @@ defimpl Phoenix.HTML.FormData, for: Map do
source: conn_or_atom_or_map,
impl: __MODULE__,
index: index,
+ action: action,
id: id <> "_" <> index_string,
name: name <> "[" <> index_string <> "]",
data: data,
diff --git a/test/phoenix_html/form_test.exs b/test/phoenix_html/form_test.exs
index cb11c45..75fb40f 100644
--- a/test/phoenix_html/form_test.exs
+++ b/test/phoenix_html/form_test.exs
@@ -138,6 +138,12 @@ defmodule Phoenix.HTML.FormTest do
assert input_changed?(form, form(%{"foo" => "bar"}), "foo")
end
+ test "input_changed? with changed action or method" do
+ form = form(%{}, action: :validate)
+ refute input_changed?(form, %{form | action: :validate}, :foo)
+ assert input_changed?(form, %{form | action: :save}, :foo)
+ end
+
describe "access" do
test "without name and atom keys" do
form =