mirror of
https://github.com/ash-project/ash_phoenix.git
synced 2024-09-19 06:42:47 +12:00
Fixes default values on dead forms (#74)
This commit is contained in:
parent
23acb72f6a
commit
bb39ba3f03
4 changed files with 84 additions and 1 deletions
|
@ -283,6 +283,16 @@ defmodule AshPhoenix.Form do
|
|||
type: :string,
|
||||
doc:
|
||||
"The http method to associate with the form. Defaults to `post` for creates, and `put` for everything else."
|
||||
],
|
||||
exclude_fields_if_empty: [
|
||||
type: {:list, {:or, [:atom, :string, {:tuple, [:any, :any]}]}},
|
||||
doc: """
|
||||
These fields will be ignored if they are empty strings.
|
||||
|
||||
This list of fields supports dead view forms. When a form is submitted from dead view
|
||||
empty fields are submitted as empty strings. This is problematic for fields that allow_nil
|
||||
or those that have default values.
|
||||
"""
|
||||
]
|
||||
]
|
||||
|
||||
|
@ -2199,6 +2209,7 @@ defmodule AshPhoenix.Form do
|
|||
form = to_form!(form)
|
||||
# These options aren't documented because they are still experimental
|
||||
hidden? = Keyword.get(opts, :hidden?, true)
|
||||
excluded_empty_fields = Keyword.get(opts, :exclude_fields_if_empty, Keyword.get(form.opts, :exclude_fields_if_empty, []))
|
||||
indexer = opts[:indexer]
|
||||
indexed_lists? = opts[:indexed_lists?] || not is_nil(indexer) || false
|
||||
transform = opts[:transform]
|
||||
|
@ -2214,7 +2225,10 @@ defmodule AshPhoenix.Form do
|
|||
|> Keyword.keys()
|
||||
|> Enum.flat_map(&[&1, to_string(&1)])
|
||||
|
||||
params = Map.drop(form.params, form_keys)
|
||||
params =
|
||||
form.params
|
||||
|> Map.drop(form_keys)
|
||||
|> exclude_empty_fields(excluded_empty_fields)
|
||||
|
||||
params =
|
||||
if only_touched? do
|
||||
|
@ -2245,6 +2259,7 @@ defmodule AshPhoenix.Form do
|
|||
nested_form = form.forms[key]
|
||||
|
||||
if nested_form && filter.(nested_form) do
|
||||
opts = Keyword.put(opts, :exclude_fields_if_empty, Keyword.get(excluded_empty_fields, key, []))
|
||||
nested_params = params(nested_form, opts)
|
||||
|
||||
if nested_params["_ignore"] == "true" do
|
||||
|
@ -4158,6 +4173,38 @@ defmodule AshPhoenix.Form do
|
|||
defp form_for_method(:create), do: "post"
|
||||
defp form_for_method(_), do: "put"
|
||||
|
||||
defp exclude_empty_fields(params, []) do
|
||||
params
|
||||
end
|
||||
|
||||
defp exclude_empty_fields(params, _) when params == %{} do
|
||||
params
|
||||
end
|
||||
|
||||
defp exclude_empty_fields(params, [unset_key | rest]) when is_atom(unset_key) do
|
||||
{_, new} =
|
||||
Map.get_and_update(params, to_string(unset_key), fn
|
||||
"" -> :pop
|
||||
nil -> :pop
|
||||
value -> {value, value}
|
||||
end)
|
||||
|
||||
exclude_empty_fields(new, rest)
|
||||
end
|
||||
|
||||
defp exclude_empty_fields(params, [{nested_type, nested_keys} | rest]) do
|
||||
{_, new} =
|
||||
Map.get_and_update(params, to_string(nested_type), fn
|
||||
nil ->
|
||||
:pop
|
||||
|
||||
map ->
|
||||
{map, exclude_empty_fields(map, nested_keys)}
|
||||
end)
|
||||
|
||||
exclude_empty_fields(new, rest)
|
||||
end
|
||||
|
||||
defimpl Phoenix.HTML.FormData do
|
||||
import AshPhoenix.FormData.Helpers
|
||||
|
||||
|
|
|
@ -600,6 +600,7 @@ defmodule AshPhoenix.LiveView do
|
|||
Phoenix.LiveView.assign(socket, one, two)
|
||||
end
|
||||
end
|
||||
|
||||
{:error, :nofile} ->
|
||||
defp assign(%Phoenix.LiveView.Socket{} = socket, one, two) do
|
||||
Phoenix.LiveView.assign(socket, one, two)
|
||||
|
|
|
@ -191,6 +191,40 @@ defmodule AshPhoenix.FormTest do
|
|||
assert form.valid? == false
|
||||
end
|
||||
|
||||
test "blank form values unset - helps support dead view forms" do
|
||||
form =
|
||||
Form.for_create(PostWithDefault, :create, api: Api, exclude_fields_if_empty: [:text, :title])
|
||||
|
||||
{:ok, post} = Form.submit(form, params: %{"title" => "", "text" => "bar"})
|
||||
assert post.text == "bar"
|
||||
assert post.title == nil
|
||||
end
|
||||
|
||||
test "blank nested form values unset - helps support dead view forms" do
|
||||
form =
|
||||
Comment
|
||||
|> Form.for_create(:create,
|
||||
api: Api,
|
||||
forms: [
|
||||
post: [
|
||||
resource: PostWithDefault,
|
||||
create_action: :create
|
||||
]
|
||||
],
|
||||
exclude_fields_if_empty: [post: [:title, :description]]
|
||||
)
|
||||
|> Form.add_form(:post)
|
||||
|
||||
{:ok, comment} =
|
||||
Form.submit(form,
|
||||
params: %{"text" => "comment", "post" => %{"title" => "", "text" => "bar"}}
|
||||
)
|
||||
|
||||
post = comment.post
|
||||
assert post.text == "bar"
|
||||
assert post.title == nil
|
||||
end
|
||||
|
||||
test "phoenix forms are accepted as input in some cases" do
|
||||
form = Form.for_create(PostWithDefault, :create, api: Api)
|
||||
form = AshPhoenix.Form.validate(form, %{"text" => ""}, errors: form.submitted_once?)
|
||||
|
|
|
@ -13,5 +13,6 @@ defmodule AshPhoenix.Test.PostWithDefault do
|
|||
attributes do
|
||||
uuid_primary_key(:id)
|
||||
attribute(:text, :string, allow_nil?: false, default: "foo")
|
||||
attribute(:title, :string)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue