Best way to process a field in a form changeset before validation

In my form, I have a price field which uses a JS hook to format it in a nicer way to the user. For example, if the user types 23432, it will display in the input element 23,432.00 The problem that I'm having is that if I send that value to be validated with AshPhoenix.Form.validate, it will fail since 23,432.00 is not a valid decimal, so what I do is run this in the params before the validation:
defp maybe_process_price(%{"price" => ""} = params), do: params

defp maybe_process_price(%{"price" => price} = params) when is_binary(price) do
price = price |> Money.parse!(:USD) |> Money.to_string(symbol: false, separator: "")

%{params | "price" => price}
end
defp maybe_process_price(%{"price" => ""} = params), do: params

defp maybe_process_price(%{"price" => price} = params) when is_binary(price) do
price = price |> Money.parse!(:USD) |> Money.to_string(symbol: false, separator: "")

%{params | "price" => price}
end
That way I first revert the price to 23432 and then send to validate. That works, but now LiveView will update my input with the value 23432 removing the correct 23,432.00. Since I can't find a reliable way to handle that from the LiveView side, I was wondering if there is a good way to add a step to my action so it will do that transformation for that field before validating the changeset? I tried using change, but that doesn't seem to work since I guess that will only run when the action is actually running, not during changeset validation.
4 Replies
Blibs
BlibsOP•3y ago
Hmm.. not sure if I messed up the post, but it is showing as solved for some reason
ZachDaniel
ZachDaniel•3y ago
🤔 so we don't currently provide a way to modify input before it is handled by types, but you could always write a custom type, or perhaps we can improve the core decimal type to know how to handle that Are you using a text input for a number? If you set it to be a number input I think it should send it back without commas
Blibs
BlibsOP•3y ago
Tbh I think this should be handled in the LiveView layer, it is just that, there is a bug there where my hook callback is not called sometimes so I can reformat the value in some places... So I was trying to find a hack/workaround to do that with the changeset/form directly 😅 But I will try to contact the LiveView devs again and see if I can make that fixed.
ZachDaniel
ZachDaniel•3y ago
We have tools in AshPhoenix.Form that you can potentially use to help. AshPhoenix.Form.for_create(…., modify_params: fn … -> So you can massage incoming data You’d have to check the docs for the exact function signature there

Did you find this page helpful?