Add default values in AshPhoenix.Form.for_create

Is it possible to setup default values for some fields of a resource during the AshPhoenix.Form.for_create form creation function? For example, let's say I'm already in live_view that knows some id that needs to be set in the resource, I don't want to expose that field in the form but set it directly in the backend.
5 Replies
ZachDaniel
ZachDaniel3y ago
Would setting defaults in the action itself work? Thats generally how I do it. With that said, you can add:
for_create(...., transform_params: fn form, params, type ->
if type == :nested do
# This is a nested form (not the top level parent)
# ...
else
# This is the top level form
Map.merge(%{"default" => "value"}, params)
end
end
)
for_create(...., transform_params: fn form, params, type ->
if type == :nested do
# This is a nested form (not the top level parent)
# ...
else
# This is the top level form
Map.merge(%{"default" => "value"}, params)
end
end
)
However, if you really don't want the value to be written to by the user, its a good idea to do that work inside the action instead.
Blibs
BlibsOP3y ago
Not sure if I got what you meant by working inside the action. I mean, my action expects a property_id, but that value is already in my socket assigns because it stores it via handle_params when it loads the liveview (ex: http://localhost:4000/property/a67ed67c-e80e-48e1-864a-8539e53be27d) What I want to do is to use that value in the form directly from the backend instead of letting the user fill that. What I did was always insert it during validation:
def handle_event("validate", %{"form" => input}, socket) do
%{assigns: %{property_id: property_id}} = socket

input = Map.put(input, "property_id", property_id)

form = AshPhoenix.Form.validate(socket.assigns.form, input)

{:noreply, assign(socket, :form, form)}
end
def handle_event("validate", %{"form" => input}, socket) do
%{assigns: %{property_id: property_id}} = socket

input = Map.put(input, "property_id", property_id)

form = AshPhoenix.Form.validate(socket.assigns.form, input)

{:noreply, assign(socket, :form, form)}
end
I will try your transform_params suggestion and see how it goes.
ZachDaniel
ZachDaniel3y ago
Ah, yeah I see what you mean. You can have private arguments, and then set them in a before_submit hook
AshPhoenix.Form.submit(..., before_submit: fn changeset ->
Ash.Changeset.set_argument(changeset, :property_id, property_id)
# or skip the private argument and do this
Ash.Changeset.force_change_attribute(changeset, :property_id, property_id)
end)
AshPhoenix.Form.submit(..., before_submit: fn changeset ->
Ash.Changeset.set_argument(changeset, :property_id, property_id)
# or skip the private argument and do this
Ash.Changeset.force_change_attribute(changeset, :property_id, property_id)
end)
Blibs
BlibsOP3y ago
Thank you, that's way better 😁 Hmm, after testing that out, it is actually not working, the before_submit function is never called and the submit function will return an error saying that property_id is required.
AshPhoenix.Form.submit(socket.assigns.form,
before_submit: fn changeset ->
IO.puts("got here")
Ash.Changeset.set_argument(changeset, :property_id, property_id)
end
)
AshPhoenix.Form.submit(socket.assigns.form,
before_submit: fn changeset ->
IO.puts("got here")
Ash.Changeset.set_argument(changeset, :property_id, property_id)
end
)
I never see the "got here" message in the terminal
ZachDaniel
ZachDaniel3y ago
🤔 Ah, yeah okay The problem is that the changeset is invalid because property_id is required 😆 In the short term, you can pass force?: true to make it call the action even though the changes are invalid

Did you find this page helpful?