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

Improve documentation of LiveViewTest.form merging behaviour #3578

Open
LostKobrakai opened this issue Dec 17, 2024 · 1 comment
Open

Improve documentation of LiveViewTest.form merging behaviour #3578

LostKobrakai opened this issue Dec 17, 2024 · 1 comment

Comments

@LostKobrakai
Copy link
Contributor

Environment

  • Elixir version (elixir -v):
  • Phoenix version (mix deps):
  • Phoenix LiveView version (mix deps): 1.0.1
  • Operating system:
  • Browsers you attempted to reproduce this bug on (the more the merrier):
  • Does the problem persist after removing "assets/node_modules" and trying again? Yes/no:

Actual behavior

The form data will be validated directly against the form markup and
make sure the data you are changing/submitting actually exists, failing
otherwise.

Expected behavior

Have an explanation how the provided data is merged with the data on the form before being submitted. I have nested records prepared on the server side and I feared providing just a subset of those on the form command would send just the data I provided, but the data provided seems to get merged with the data present in the form. This seems to also allow just providing the value, which changed to form/3 for updating just that part of a form without caring for other values, which can be really useful.

@SteffenDE
Copy link
Collaborator

@LostKobrakai the values you pass are validated against the markup in the following way:

  1. for each key that is passed, we check that we find an input / select or textarea node in the HTML with the correct name

    %{foo: %{bar: %{baz: "test"}}}

    would require an input with name="foo[bar][baz]", etc.

  2. check that the type of the found element is not "submit" or "image"

  3. for selects, check that the given value is a valid option, based on the rendered options

Some of the relevant code is here

@limited ["select", "multiple select", "checkbox", "radio", "hidden"]
@forbidden ["submit", "image"]
defp fill_in_value(non_string_value, name, node) do
value = stringify(non_string_value, &to_string/1)
name = if is_list(value), do: name <> "[]", else: name
{types, dom_values} =
node
|> DOM.filter(fn node ->
DOM.attribute(node, "name") == name and is_nil(DOM.attribute(node, "disabled"))
end)
|> collect_values([], [])
limited? = Enum.all?(types, &(&1 in @limited))
cond do
calendar_value = calendar_value(types, non_string_value, name, node) ->
{:ok, calendar_value}
types == [] ->
{:error, :invalid,
"could not find non-disabled input, select or textarea with name #{inspect(name)} within:\n\n" <>
DOM.inspect_html(DOM.all(node, "[name]"))}
forbidden_type = Enum.find(types, &(&1 in @forbidden)) ->
{:error, :invalid,
"cannot provide value to #{inspect(name)} because #{forbidden_type} inputs are never submitted"}
forbidden_value = limited? && value |> List.wrap() |> Enum.find(&(&1 not in dom_values)) ->
{:error, :invalid,
"value for #{hd(types)} #{inspect(name)} must be one of #{inspect(dom_values)}, " <>
"got: #{inspect(forbidden_value)}"}
true ->
{:ok, value}
end
end

Here's a playground: https://gist.github.com/SteffenDE/ccda65c6b2ea81aefae723d503610b62

If you want, feel free to open a PR to clarify this in the docs :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants