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

Can I use struct in Phoenix.HTML.Form.params? #3661

Closed
rapidfsub opened this issue Feb 5, 2025 · 6 comments
Closed

Can I use struct in Phoenix.HTML.Form.params? #3661

rapidfsub opened this issue Feb 5, 2025 · 6 comments

Comments

@rapidfsub
Copy link

defmodule Phoenix.Component do
  # ...
  def used_input?(%Phoenix.HTML.FormField{field: field, form: form}) do
    used_param?(form.params, field)
  end

  defp used_param?(_params, "_unused_" <> _), do: false

  defp used_param?(params, field) do
    field_str = "#{field}"
    unused_field_str = "_unused_#{field}"

    case params do
      %{^field_str => _, ^unused_field_str => _} -> false
      %{^field_str => %{} = nested} -> Enum.any?(Map.keys(nested), &used_param?(nested, &1))
      %{^field_str => _val} -> true
      %{} -> false
    end
  end
  # ...
end

In normal case, "the value of ^field_str key in params map" would be a string or a map with string keys.
But with ash_phoenix I can set it as a struct, i.e. Decimal.
With struct value, used_input?/1 always returns false, because nested is a map with only atom keys.

Is it proper to assign struct in params? Then this could be a bug.
Or, is it not intended to assign struct in params?

@SteffenDE
Copy link
Collaborator

Hey @rapidfsub,

the params of a %Phoenix.HTML.Form{} are supposed to have string keys, see https://hexdocs.pm/phoenix_html/Phoenix.HTML.Form.html#t:t/0. Can you clarify when you're seeing structs?

Some helpful things you could do are:

  1. post what dbg(form, limit: :infinity, structs: false) returns
  2. give more details how you create the form struct (e.g. what you pass to <.form for={}> or Phoenix.Component.to_form/2.

@rapidfsub
Copy link
Author

@SteffenDE
It's not common case for normal phoenix app.
But with ash_phoenix, I can set the value in params to be a struct.
There are prepare_params and transform_params callback features in ash_phoenix.
It's my intention.

My question is "Is this allowed, or not recommended?"

@SteffenDE
Copy link
Collaborator

My question is "Is this allowed, or not recommended?"

The current typespec doesn't allow it: https://hexdocs.pm/phoenix_html/Phoenix.HTML.Form.html#t:t/0

params: %{required(binary()) => term()},

Is this officially encouraged by Ash anywhere?

@rapidfsub
Copy link
Author

rapidfsub commented Feb 10, 2025

Is this officially encouraged by Ash anywhere?

No. But it is just possible to do.

@rapidfsub
Copy link
Author

params: %{required(binary()) => term()},

@SteffenDE
I think typespec term() means, "struct is allowed", isn't it?

@SteffenDE
Copy link
Collaborator

You're right. The spec actually allows the values in the params to be anything, but for nested form values, LiveView expects those to be maps with string keys as well. I don't think this is something want to change, so I'd encourage you to ensure that you pass nested parameters a maps with string keys too.

@SteffenDE SteffenDE closed this as not planned Won't fix, can't repro, duplicate, stale Feb 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants