AE
Ash Elixirโ€ข3y ago
axdc

Multiple checkbox group with Ash Forms

Is there a recommended guide to implementing something similar to the checkboxgroup component featured in https://fly.io/phoenix-files/making-a-checkboxgroup-input/ but compatible with Ash's form helpers? I've been working through that guide but it doesn't seem to play nice with the resources and forms I have. Been trying to munge my data into the right shape and now I'm wondering if there's an existing component system for this I'm overlooking (I've heard about Surface but I'm under the impression it may have been superseded by heex?)
Fly
Making a CheckboxGroup Input
Creating a custom core_component input for tagging items using a multi-select checkbox group.
14 Replies
ZachDaniel
ZachDanielโ€ข3y ago
Hey there! Sorry I've left you hanging for a bit. I'd have to see an example of how its not playing nicely with AshPhoenix.Form stuff. What you probably need is a way to configure that certain paths don't get auto? generated, that way you can specify them as a checkbox list and have it sent to the action as a list of values. The value_is_key option on managed relationships might help there. although may not be necessary if the checkbox maps to the ids, then you'd just have argument :related_things, {:array, :uuid}
axdc
axdcOPโ€ข3y ago
No problem. Thank you. For the checkgroup, I'm not certain exactly what's going on but I think validations are tripping up, and I also had to remove the checked={value in @value} bit from the guide to get it to compile so they aren't staying checked when the liveview rerenders Right now I have the action:
create :commander_create do
argument :relate_plans, {:array, :uuid} do
allow_nil? false
end
change Panacea.Sites.Changes.SlugifyTitle

change manage_relationship(:relate_plans, :plans,
on_lookup: :relate,
on_no_match: :ignore,
on_missing: :unrelate,
on_match: :ignore
)
end
create :commander_create do
argument :relate_plans, {:array, :uuid} do
allow_nil? false
end
change Panacea.Sites.Changes.SlugifyTitle

change manage_relationship(:relate_plans, :plans,
on_lookup: :relate,
on_no_match: :ignore,
on_missing: :unrelate,
on_match: :ignore
)
end
new.ex:
def mount(_params, _session, socket) do
form =
AshPhoenix.Form.for_create(Post, :commander_create,
api: Panacea.Sites,
forms: [auto?: true],
actor: socket.assigns.current_user
)
|> to_form

plans = Panacea.Sites.Plan.read_all!(actor: socket.assigns.current_user)

plans_options =
for plan <- plans do
{plan.name, plan.id}
end

socket =
socket
|> assign(:page_title, "New Post")
|> assign(form: form)
|> assign(plans: plans)
|> assign(plans_options: plans_options)

{:ok, socket}
end
def mount(_params, _session, socket) do
form =
AshPhoenix.Form.for_create(Post, :commander_create,
api: Panacea.Sites,
forms: [auto?: true],
actor: socket.assigns.current_user
)
|> to_form

plans = Panacea.Sites.Plan.read_all!(actor: socket.assigns.current_user)

plans_options =
for plan <- plans do
{plan.name, plan.id}
end

socket =
socket
|> assign(:page_title, "New Post")
|> assign(form: form)
|> assign(plans: plans)
|> assign(plans_options: plans_options)

{:ok, socket}
end
new.html.heex:
<.simple_form :let={f} for={@form} phx-change="validate" phx-submit="create">
<.input label="Title" field={@form[:title]} />
<.input label="Content" type="textarea" field={@form[:content]} />

<.checkgroup field={@form[:relate_plans]} label="Plans" options={@plans_options} />

<.button class="h-fit mt-14">Create</.button>
</.simple_form>
<.simple_form :let={f} for={@form} phx-change="validate" phx-submit="create">
<.input label="Title" field={@form[:title]} />
<.input label="Content" type="textarea" field={@form[:content]} />

<.checkgroup field={@form[:relate_plans]} label="Plans" options={@plans_options} />

<.button class="h-fit mt-14">Create</.button>
</.simple_form>
I think I'm setting them up incompletely and I also know some custom validation might be required? This sounds right, like you'd just be checking off the IDs that are going to be associated with this post, and then I should handle them in my action and a validation error comes back immediately at index 0 no nil values which I suspect is due to the empty first value from the hidden input, which the guide specifies is required so it never sends an empty response
ZachDaniel
ZachDanielโ€ข3y ago
Interesting... You could make your argument accept nil values and filter them out its a bit strange though
axdc
axdcOPโ€ข3y ago
I would like to do it in a not-strange way ๐Ÿ˜“
ZachDaniel
ZachDanielโ€ข3y ago
Its hard without having my hands on it, but the basic issue here is that you need it to send back an empty list when nothing is checked right? Have you confirmed that it doesn't have the behavior you want without the hidden field?
axdc
axdcOPโ€ข3y ago
Confirmed that with or without the hidden field, the checked values don't stay checked
frankdugan3
frankdugan3โ€ข15mo ago
@axdc Did you ever get this sorted out? Currently adapting the same guide and running into the same issue. ๐Ÿ˜„ Though, my case is much simpler, just a list of strings.
axdc
axdcOPโ€ข15mo ago
okay so the answer is yes because it works, but I absolutely don't remember how. reviewing the code now
frankdugan3
frankdugan3โ€ข15mo ago
Awesome, thanks!
axdc
axdcOPโ€ข15mo ago
for sure! might be dragons, haven't touched this in a while, had a lot going on but things have changed and i should get to be active with elixir again very soon ๐Ÿ™‚
frankdugan3
frankdugan3โ€ข15mo ago
Turns out my problem was super simple. The value in @value check wasn't working because I was using ci_string, had to cast the elements in @value for comparison. ๐Ÿคฆโ€โ™‚๏ธ

Did you find this page helpful?