Skip to content

Commit

Permalink
Consider form action and method changing as changed
Browse files Browse the repository at this point in the history
  • Loading branch information
chrismccord committed Feb 5, 2024
1 parent c50f33d commit 5f6e91a
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 4 deletions.
13 changes: 9 additions & 4 deletions lib/phoenix_html/form.ex
Expand Up @@ -64,6 +64,8 @@ defmodule Phoenix.HTML.Form do
id: nil,
name: nil,
data: nil,
action: nil,
method: nil,
hidden: [],
params: %{},
errors: [],
Expand All @@ -74,6 +76,8 @@ defmodule Phoenix.HTML.Form do
source: Phoenix.HTML.FormData.t(),
name: String.t(),
data: %{field => term},
action: nil | atom() | String.t(),
method: nil | atom() | String.t(),
params: %{binary => term},
hidden: Keyword.t(),
options: Keyword.t(),
Expand Down Expand Up @@ -191,9 +195,9 @@ 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, method, 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?(
Expand All @@ -202,7 +206,8 @@ defmodule Phoenix.HTML.Form do
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 form1.action != form2.action or
form1.method != form2.method or
field_errors(errors1, field) != field_errors(errors2, field) or
impl1.input_value(source1, form1, field) != impl2.input_value(source2, form2, field)
end
Expand Down
14 changes: 14 additions & 0 deletions lib/phoenix_html/form_data.ex
Expand Up @@ -56,6 +56,10 @@ defprotocol Phoenix.HTML.FormData do
applies if the field value is a list and no parameters were
sent through the form.
* `:action` - The form action, such as the HTML `action` attribute
or LiveView action.
* `:method` - The form method, such as the HTML `method` attribute.
"""
@spec to_form(t, Phoenix.HTML.Form.t(), Phoenix.HTML.Form.field(), Keyword.t()) ::
[Phoenix.HTML.Form.t()]
Expand All @@ -79,6 +83,8 @@ 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)
{method, opts} = Keyword.pop(opts, :method, nil)
id = Keyword.get(opts, :id) || name

unless is_binary(id) or is_nil(id) do
Expand All @@ -93,6 +99,8 @@ defimpl Phoenix.HTML.FormData, for: Map do
params: params,
data: %{},
errors: errors,
action: action,
method: method,
options: opts
}
end
Expand All @@ -118,6 +126,8 @@ 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)
{method, opts} = Keyword.pop(opts, :method)

id = to_string(id || form.id <> "_#{field}")
name = to_string(name || form.name <> "[#{field}]")
Expand All @@ -133,6 +143,8 @@ defimpl Phoenix.HTML.FormData, for: Map do
id: id,
name: name,
data: default,
action: action,
method: method,
params: params || %{},
hidden: hidden,
options: opts
Expand All @@ -157,6 +169,8 @@ defimpl Phoenix.HTML.FormData, for: Map do
source: conn_or_atom_or_map,
impl: __MODULE__,
index: index,
action: action,
method: method,
id: id <> "_" <> index_string,
name: name <> "[" <> index_string <> "]",
data: data,
Expand Down
7 changes: 7 additions & 0 deletions test/phoenix_html/form_test.exs
Expand Up @@ -138,6 +138,13 @@ 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, method: "post")
refute input_changed?(form, %{form | action: :validate, method: "post"}, :foo)
assert input_changed?(form, %{form | action: :save}, :foo)
assert input_changed?(form, %{form | method: "put"}, :foo)
end

describe "access" do
test "without name and atom keys" do
form =
Expand Down

0 comments on commit 5f6e91a

Please sign in to comment.