Comments (7)
@sevenseacat feel free to reopen if you see more issues along these lines.
from ash_phoenix.
So after thinking about this a bit more, I think the actual answer here is for the data to come back from the action with the resulting relationship loaded, and already sorted. This would only work in some cases, specifically when the entire relationship needs to be loaded, or in cases where we are performing a create action and are creating related records. However, if you aren't in one of those cases, you almost certainly aren't expecting to save the form and then get records back in the same order anyway, because if you load the relationship you'll get more than you sent back. So the pattern would look something like this:
case Form.submit(form) do
{:ok, result} ->
assign_form(socket, result)
{:error, form} ->
assign(socket, :form, form)
end
...
defp assign_form(socket, thing_you_are_updating) do
thing_you_are_updating
|> Api.load!([relationship: :foo], lazy?: true) # the `lazy?: true` will keep anything that is already loaded, and the edited relationship will be loaded as a result of the action
|> AshPhoenix.Form.for_update(...)
end
from ash_phoenix.
Actually...looks like we're already doing this in core :) @sevenseacat perhaps you could try using a lazy?: true
load as illustrated above and see if that works for you?
from ash_phoenix.
Originally the reason I was reloading all of the data was because relationships weren't coming back on the record after update, meaning re-rendering the form was erroring - that doesn't seem to happen anymore which is good! I can remove that reloading-data loop entirely.
However, the data is still being returned by the action in a different order.
eg.
dbg(AshPhoenix.Form.value(socket.assigns.element_form, :tool_specifications))
dbg(params)
case AshPhoenix.Form.submit(socket.assigns.element_form, params: params) do
{:ok, updated_element} ->
dbg(updated_element.tool_specifications)
gives:
AshPhoenix.Form.value(socket.assigns.element_form, :tool_specifications) #=> [
%{
"_form_type" => "update",
"id" => "abdab2a1-a221-43fe-be50-1add1a40cf8f",
"quantity" => "1431",
"specification_id" => "ea9544d9-5d5a-4014-9a59-335719bcd2ea",
},
%{
"_form_type" => "update",
"id" => "a3bc5d69-b683-4e42-83df-9a24eb9a2881",
"quantity" => "21",
"specification_id" => "022e2e06-fbe9-41d9-9860-4d67ca8a73c0",
}
]
params #=> %{
# other stuff
"tool_specifications" => %{
"0" => %{
"_form_type" => "update",
"_touched" => "_form_type,id,quantity,specification_id",
"id" => "abdab2a1-a221-43fe-be50-1add1a40cf8f",
"quantity" => "1431",
"specification_id" => "ea9544d9-5d5a-4014-9a59-335719bcd2ea",
},
"1" => %{
"_form_type" => "update",
"_touched" => "_form_type,id,quantity,specification_id",
"id" => "a3bc5d69-b683-4e42-83df-9a24eb9a2881",
"quantity" => "21",
"specification_id" => "022e2e06-fbe9-41d9-9860-4d67ca8a73c0",
}
}
}
updated_element.tool_specifications #=> [
#MyApp.Element.ToolSpecification<
specification: #MyApp.Tool.Specification<>,
__meta__: #Ecto.Schema.Metadata<:loaded, "element_tool_specifications">,
id: "a3bc5d69-b683-4e42-83df-9a24eb9a2881",
quantity: 21,
inserted_at: ~U[2022-10-17 06:16:24.635005Z],
updated_at: ~U[2022-10-19 01:12:37.432723Z],
element_id: "a8316188-2fe2-4ddb-a9b4-e02cb209bbac",
specification_id: "022e2e06-fbe9-41d9-9860-4d67ca8a73c0",
aggregates: %{},
calculations: %{},
__order__: nil,
...
>,
#MyApp.Element.ToolSpecification<
specification: #MyApp.Tool.Specification<>,
element: #Ash.NotLoaded<:relationship>,
__meta__: #Ecto.Schema.Metadata<:loaded, "element_tool_specifications">,
id: "abdab2a1-a221-43fe-be50-1add1a40cf8f",
quantity: 1431,
inserted_at: ~U[2022-10-17 05:53:26.206812Z],
updated_at: ~U[2022-10-19 01:13:16.172939Z],
element_id: "a8316188-2fe2-4ddb-a9b4-e02cb209bbac",
specification_id: "ea9544d9-5d5a-4014-9a59-335719bcd2ea",
aggregates: %{},
calculations: %{},
__order__: nil,
...
>
]
from ash_phoenix.
Okay, yeah I can see that. I guess the current behavior just doesn't do the work to preserve order. I'll take a look in the morning.
from ash_phoenix.
I'm actually pretty sure its just reversing the inputs, because as we apply the inputs we do things like [result | relationship_value]
. So I'll toss in an Enum.reverse
in and I think we'll be good :)
from ash_phoenix.
Alright, so this should be fixed in ash main
. Anyone else looking: if you are loading data after submitting a form, you will want to use lazy?: true
so as not to potentially reorder the relationship after editing it.
from ash_phoenix.
Related Issues (20)
- Syntax error in ash_phoenix.gen.live generated code. HOT 1
- Duplicate error messages on embedded form HOT 2
- mix ash_phoenix.gen.live Error HOT 1
- Invalid select input for atom attributes with one_of constraint
- mix ash_phoenix.gen.live doesn't add fields to show.ex HOT 3
- `keep_live` access callback result in `subscribe` HOT 1
- Support phoenix_html 4.0 on new phoenix apps HOT 1
- `Form.for_create` and `Form.for_update` don't seem to validate that the action exists with that method
- Write a LiveView specific tutorial HOT 2
- Write a Phoenix Contexts -> Ash Resources guide HOT 2
- Documentation Example Error HOT 2
- An ability to drop some values from the form struct HOT 1
- Missing logo file causes `mix doc` to fail. HOT 2
- Form Validation crashes on invalid values in decimal-fields HOT 3
- Phoenix 1.7 version? HOT 2
- AshPhoenix.Form.submit doesn't apply `change` from action. HOT 4
- Broken "philosophy" link in https://github.com/ash-project/ash_phoenix/blob/v1.2.10/documentation/tutorials/getting-started-with-ash-and-phoenix.md HOT 1
- Rename `FilterForm.to_filter!` HOT 1
- Documentation for `accessing_from` does not exist (or I can't find it) HOT 1
- Setting actor in nested forms HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ash_phoenix.