Skip to content

Commit

Permalink
Support string fields in input_changed?/3 (#428)
Browse files Browse the repository at this point in the history
  • Loading branch information
dvic committed Aug 15, 2023
1 parent 0d394e9 commit 2597c1d
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 6 deletions.
16 changes: 11 additions & 5 deletions lib/phoenix_html/form.ex
Expand Up @@ -74,7 +74,7 @@ defmodule Phoenix.HTML.Form do
params: %{binary => term},
hidden: Keyword.t(),
options: Keyword.t(),
errors: Keyword.t(),
errors: [{field, term}],
impl: module,
id: String.t(),
index: nil | non_neg_integer,
Expand All @@ -100,7 +100,7 @@ defmodule Phoenix.HTML.Form do
defp fetch(%{errors: errors} = form, field, field_as_string) do
{:ok,
%Phoenix.HTML.FormField{
errors: for({^field, value} <- errors, do: value),
errors: field_errors(errors, field),
field: field,
form: form,
id: input_id(form, field_as_string),
Expand Down Expand Up @@ -193,15 +193,15 @@ defmodule Phoenix.HTML.Form do
changed. This is mostly used for optimization engines as an extension
of the `Access` behaviour.
"""
@spec input_changed?(t, t, atom) :: boolean()
@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,
field
)
when is_atom(field) do
when is_atom(field) or is_binary(field) do
impl1 != impl2 or id1 != id2 or name1 != name2 or
Keyword.get_values(errors1, field) != Keyword.get_values(errors2, field) 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 Expand Up @@ -1813,4 +1813,10 @@ defmodule Phoenix.HTML.Form do
# Normalize field name to string version
defp field_to_string(field) when is_atom(field), do: Atom.to_string(field)
defp field_to_string(field) when is_binary(field), do: field

# Helper for getting field errors, handling string fields
defp field_errors(errors, field)
when is_list(errors) and (is_atom(field) or is_binary(field)) do
for {^field, error} <- errors, do: error
end
end
11 changes: 10 additions & 1 deletion test/phoenix_html/form_test.exs
Expand Up @@ -118,7 +118,7 @@ defmodule Phoenix.HTML.FormTest do
end
end

test "input_changed?" do
test "input_changed? with atom fields" do
form = form(%{})
refute input_changed?(form, form, :foo)
assert input_changed?(form, %{form | errors: [foo: "bar"]}, :foo)
Expand All @@ -127,6 +127,15 @@ defmodule Phoenix.HTML.FormTest do
assert input_changed?(form, form(%{"foo" => "bar"}), :foo)
end

test "input_changed? with string fields" do
form = form(%{})
refute input_changed?(form, form, "foo")
assert input_changed?(form, %{form | errors: [{"foo", "bar"}]}, "foo")
assert input_changed?(form, %{form | name: "another"}, "foo")
assert input_changed?(form, %{form | id: "another"}, "foo")
assert input_changed?(form, form(%{"foo" => "bar"}), "foo")
end

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

0 comments on commit 2597c1d

Please sign in to comment.