zer3f
How to get transaction result of previous forms data of a resource and pass through next resource in AshPhoenix.Form.Submit?
Hello,
I have a form that consists of multiple resources to submit. AshPhoenix.Form helped to render nested forms easily using add_form and submit using AshPhoenix.Form.Submit. But i need some help regarding, getting the pervious value of the form. Please go through these details, this is a registration form that has a flow like this:
- Register user
- Get the id from the step 1, and add it to user_personal_details (Action already accepts
user_id) along with other params like first_name, last_name etc in the resource - Register Company.
- Add company id from 3 to update registered user in 1 with company_id.
I have setup all the resources, domains and default actions with relationships. This kind of flow used to do it in a transaction with ecto’s Multi.New() function. But I wonder if I can simplify this process using the existing function AshPhoenix.Form.Submit or any other Ash’s way. Please let me know I need to share source code.
Thank you.
Marked As Solved
zachdaniel
Ah, I see what you mean. Using multiple explicit forms like that only really helps with the form structure itself. You should first be looking at how to implement this logic in your actions, and then work on the form logic, which likely would not require those nested forms once you are ready. Unfortunately I don’t have time to go through your entire code and craft an answer for your specific case, but I can provide a basic example.
# on your user resource
create :register do
argument :company_name, :string, allow_nil?: false
change fn changeset, _ ->
Ash.Changeset.before_action(changeset, fn changeset, _ ->
org = create_organization(changeset.arguments.company_name)
Ash.Changeset.force_change_attributes(changeset, :company_id, company.id)
end)
end
end
Using “hooks” (Ash.Changeset.before_action, Ash.Changeset.after_action, etc.) allow us to build progressively more complex multi-step actions. Additionally, we can use arguments to accept additional inputs that don’t map directly to attributes to be changed.
With that, you can create a single form with all the inputs you need, no need to define nested forms.
Using manage_relationship
Given that what you are doing is essentially creating related data as part of an action, there is a builtin that can help with this, called manage_relationship.
You can use it like so:
create :register do
argument :personal_information, :map, allow_nil?: false
argument :company_information, :map, allow_nil?: false
change manage_relationship(:personal_information, type: :create)
change manage_relationship(:personal_information, type: :create)
end
Then, when creating your form, you can use auto?: true, which will automatically detect the necessary nested forms. The two in combination should be all you need to accomplish your stated goal.
AshPhoenix.Form.for_create(
Mgx.Accounts.User,
:register_with_password,
forms: [
auto?: true
]
)
|> AshPhoenix.Form.add_form([:personal_information])
|> AshPhoenix.Form.add_form([:company_information])
|> to_form()
Also Liked
zer3f
I see, Now I understood the flow of it. Thank you. Much appreciated.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









