AshPhoenix Form use for `many_to_many` relationships through `append_and_remove` management
Hi all, and thanks for this amazing project!
Today I'm trying to figure out how to use AshPhoenix.Form with field of type
{:array, :uuid}
, for example in the context of managing a many_to_many
relationships through append_and_remove
, in extension of your example here https://hexdocs.pm/ash/2.6.18/managing-relationships.html.
For example, I have this resources with the desired result of allowing the user to select a list of tags from a multiple select:
defmodule Post do
use Ash.Resource, data_layer: AshPostgres.DataLayer
postgres do
table "posts"
repo Repo
end
attributes do
uuid_primary_key(:id)
attribute(:title, :string)
attribute(:content, :string)
end
relationships do
many_to_many :tags, Tag do
through PostTag
source_attribute_on_join_resource :post_id
destination_attribute_on_join_resource :tag_id
end
end
actions do
update :set_tags do
argument :tags, {:array, :uuid}
change manage_relationship(:tags, type: :append_and_remove)
end
end
defmodule Tag do
use Ash.Resource, data_layer: AshPostgres.DataLayer
postgres do
table "tags"
repo Repo
end
attributes do
uuid_primary_key(:id)
attribute(:name, :string)
end
relationships do
many_to_many :posts, Post do
through PostTag
source_attribute_on_join_resource :tag_id
destination_attribute_on_join_resource :post_id
end
end
end
defmodule PostTag do
use Ash.Resource, data_layer: AshPostgres.DataLayer
postgres do
table "post_tags"
repo Repo
end
attributes do
uuid_primary_key(:id)
end
relationships do
belongs_to :post, Post, allow_nil?: false
belongs_to :tag, Tag, allow_nil?: false, attribute_writable?: true
end
end
With this in place, how can I use AshPhoenix.Form auto-form and/or inputs_for for generating the post[tags][]
fields in a clean way?7 Replies
So you’d want a
manage_relationship …
using the value_is_key
option set to :id
And then in your form, you’d do inputs_for
as normal, setting the id
field in the nested form, and it will be transformed before submission to be just the id instead of a map.Hi @Zach Daniel,
thank you for your help but in the meantime I think that I've found the issue and the solution is a little different from your suggestion: let me explain so that maybe we can help someone else in the future through this post.
After posting here I've continued trying to resolve my problem and while reading the AshPhoenix source code, I've found this test https://github.com/ash-project/ash_phoenix/blob/main/test/auto_form_test.exs#L33 with this related resource https://github.com/ash-project/ash_phoenix/blob/main/test/support/resources/post.ex#L29 which turn me in the right direction.
So in my projects liveview I've replaced the
forms: [auto?: true]
with forms: AshPhoenix.Form.Auto.auto(Post, :set_tags, include_non_map_types?: true)
and now I can use inputs_for form[:tags]
with a input nested_form[:id]
inside and everything works like expected (in reality I've a LiveComponent that show a dropdown with all the available options and then call add_form
and remove_form
when user click on the options for creating the sub-forms with only a hidden input for each id).
After your response I've tried to replace the resource change manage_relationship(:tags, type: :append_and_remove)
with change manage_relationship(:tags, type: :append_and_remove, value_is_key: :id)
but this make no difference for the forms: [auto?: true]
functionality.
So that replace alone don't resolve the issue and with the solution of calling AshPhoenix.Form.Auto.auto
I've experimenting that having or not the value_is_key: :id
option makes no difference.
So maybe should forms: [auto?: true]
have the include_non_map_types?
true as default? Or maybe can we have something like forms: [auto?: [include_non_map_types?: true, other_opts...]]
for cases like these?Ah, right you are. I forgot about that option.
🤔 yeah, I'd have to think about that
in terms of making it the default
There may be some backwards compatibility issues
Could you do me a favor and lodge an issue in the
ash_phoenix
repo with the information provided above? We can find a way to improve that experience, and maybe that looks like setting a different default value for that field as you suggested.Oh, right
Sure, I will.
If you can't make that default for backwards compatibility what about the idea of allowing also a list of opts for
auto?
instead of true
too?
For now maybe a little documentation for the include_non_map_types?
should be enoughcan you try
ash_phoenix
main
?
It now supports forms: [auto?: [include_non_map_types?: true]]
When published to hex/ash_hq it will also show documentation of the available options in the module docs.Wow, you won!
You were so fast that I didn't even have the time to open the issue on github 🚀
I confirm that now works with your latest commit on main 👏 and that
value_is_key
is not necessary in this case.
Le me thank you so much for this project and for you reactiveness and kindness with the community!Glad we got it worked out. LMK if you have any other questions 🙂
And thanks for the kind words.