Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add form action and consider input changed if action changes #439

Merged
merged 5 commits into from Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 6 additions & 4 deletions lib/phoenix_html/form.ex
Expand Up @@ -64,6 +64,7 @@ defmodule Phoenix.HTML.Form do
id: nil,
name: nil,
data: nil,
action: nil,
hidden: [],
params: %{},
errors: [],
Expand All @@ -74,6 +75,7 @@ defmodule Phoenix.HTML.Form do
source: Phoenix.HTML.FormData.t(),
name: String.t(),
data: %{field => term},
action: nil | atom() | String.t(),
josevalim marked this conversation as resolved.
Show resolved Hide resolved
params: %{binary => term},
hidden: Keyword.t(),
options: Keyword.t(),
Expand Down Expand Up @@ -191,9 +193,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, 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 +204,7 @@ 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
chrismccord marked this conversation as resolved.
Show resolved Hide resolved
field_errors(errors1, field) != field_errors(errors2, field) or
impl1.input_value(source1, form1, field) != impl2.input_value(source2, form2, field)
end
Expand Down
7 changes: 7 additions & 0 deletions lib/phoenix_html/form_data.ex
Expand Up @@ -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 form action, such as the HTML `action` attribute
or LiveView action.
chrismccord marked this conversation as resolved.
Show resolved Hide resolved
"""
@spec to_form(t, Phoenix.HTML.Form.t(), Phoenix.HTML.Form.field(), Keyword.t()) ::
[Phoenix.HTML.Form.t()]
Expand All @@ -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
Expand All @@ -93,6 +96,7 @@ defimpl Phoenix.HTML.FormData, for: Map do
params: params,
data: %{},
errors: errors,
action: action,
options: opts
}
end
Expand All @@ -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}]")
Expand All @@ -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
Expand All @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions test/phoenix_html/form_test.exs
Expand Up @@ -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 =
Expand Down