How to set a default value for AshPhoenix.Form.for_action ?

I have a Resource that has a foreign key in it which I assign as a hidden field in my form. How do I make it so that I can fill out the foreign key field when calling AshPhoenix.Form.for_action or AshPhoenix.Form.for_create?
3 Replies
ZachDaniel
ZachDaniel•3y ago
There are two main ways to do it. 1. use prepare_source coupled with before_submit to set the belongs_to on the changeset. Looks different depending on if you are setting arguments/attributes, but here is an example
# when creating the form
AshPhoenix.Form.for_create(...., prepare_source: fn changeset ->
Ash.Changeset.set_argument(changeset, :foo_id, <the_id>)
end)

# when submitting the form
AshPhoenix.Form.submit(..., before_submit: fn changeset ->
Ash.Changeset.set_argument(changeset, :foo_id, <the_id>)
end)
# when creating the form
AshPhoenix.Form.for_create(...., prepare_source: fn changeset ->
Ash.Changeset.set_argument(changeset, :foo_id, <the_id>)
end)

# when submitting the form
AshPhoenix.Form.submit(..., before_submit: fn changeset ->
Ash.Changeset.set_argument(changeset, :foo_id, <the_id>)
end)
The before_submit is important to make sure that someone doesn't mess with the underlying form HTML to set foo_id after our prepare_source runs. The flow there is prepare_source -> pass user input to action -> before_submit. You can also use private arguments for this purpose, which means the value won't be accepted from user input, only with explicit calls to Ash.Changeset.set_argument That would avoid the need for the before_submit hook in addition to the rest. 2. Put the action on the parent thing. For example:
update :add_child do
accept []
argument :child, :map, allow_nil?: false

change manage_relationship(:child, :children, type: :create) # child input will be used to create a child
end
update :add_child do
accept []
argument :child, :map, allow_nil?: false

change manage_relationship(:child, :children, type: :create) # child input will be used to create a child
end
Then
parent_record
|> AshPhoenix.Form.for_update(:add_child, forms: [auto?: true])
|> AshPhoenix.Form.add_form(:child) # populate an empty form for the `child` argument
parent_record
|> AshPhoenix.Form.for_update(:add_child, forms: [auto?: true])
|> AshPhoenix.Form.add_form(:child) # populate an empty form for the `child` argument
And in your HTML
<%= for child <- inputs_for(form, :child) do %>
...html inputs for child form
<% end %>
<%= for child <- inputs_for(form, :child) do %>
...html inputs for child form
<% end %>
If you do that, Ash will take care of relating the child with the parent, because thats what manage_relationship does.
Terryble
TerrybleOP•3y ago
This is so detailed. Thanks for helping!
ZachDaniel
ZachDaniel•3y ago
My pleasure 😄

Did you find this page helpful?