Ash Form Questions

Are there any gotchas with AshPhoenix.Form.create_for and child resources inside an inputs_for? I'm getting an unkown error and I'm not sure what's going wrong because the example in the documentation seems to indicate that the child object in a has_many relationship just gets created?
resource |>
Form.for_create(action,
api: api,
forms: forms,
prepare_source: prepare_source
)

resource |>
Form.for_create(action,
api: api,
forms: forms,
prepare_source: prepare_source
)

forms={[
answers: [
type: :list,
resource: PollAnswer,
create_action: :create
]
]}

forms={[
answers: [
type: :list,
resource: PollAnswer,
create_action: :create
]
]}

<fieldset>
<legend>Answers</legend>
<.inputs_for :let={f_answer} field={f[:answers]}>
<.input field={f_answer[:label]} label="Label" />
<.icon
phx-click="remove_form"
phx-value-path={f_answer.name}
phx-target={"##{@id}"}
name="hero-minus"
/>
</.inputs_for>
<menu>
<.icon
phx-click="add_form"
phx-value-path={f[:answers].name}
phx-target={"##{@id}"}
name="hero-plus"
/>
</menu>
</fieldset>
<fieldset>
<legend>Answers</legend>
<.inputs_for :let={f_answer} field={f[:answers]}>
<.input field={f_answer[:label]} label="Label" />
<.icon
phx-click="remove_form"
phx-value-path={f_answer.name}
phx-target={"##{@id}"}
name="hero-minus"
/>
</.inputs_for>
<menu>
<.icon
phx-click="add_form"
phx-value-path={f[:answers].name}
phx-target={"##{@id}"}
name="hero-plus"
/>
</menu>
</fieldset>
My guess is that there's something I need to opt into configuration wise in the resource to ahve this work?
24 Replies
ZachDaniel
ZachDaniel•2y ago
What is forms in your call to Forms.for_create?
WIGGLES
WIGGLESOP•2y ago
its a component prop let me split out the code blocks again
ZachDaniel
ZachDaniel•2y ago
Mostly I mean what is the value of that variable the value of the forms option determines what child forms are available
WIGGLES
WIGGLESOP•2y ago
oh answers: [ type: :list, resource: PollAnswer, create_action: :create ] child list of a resource at the many end of a one to many relationship
ZachDaniel
ZachDaniel•2y ago
gotcha, and whats the error that you're getting?
WIGGLES
WIGGLESOP•2y ago
[error] GenServer #PID<0.3292.0> terminating
** (Ash.Error.Unknown) Unknown Error

* []
(elixir 1.14.4) lib/enum.ex:1658: Enum."-map/2-lists^map/1-0-"/2
(ash 2.9.5) lib/ash/error/error.ex:207: Ash.Error.to_error_class/2
(ash_phoenix 1.2.13) lib/ash_phoenix/form/form.ex:1646: AshPhoenix.Form.submit/2
(ash_phoenix 1.2.13) lib/ash_phoenix/form/form.ex:1666: AshPhoenix.Form.submit!/2
(butsby 0.1.0) lib/butsby_web/components/forms.ex:75: ButsbyWeb.Components.Forms.handle_event/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:630: anonymous fn/4 in Phoenix.LiveView.Channel.inner_component_handle_event/4
(telemetry 1.2.1) /home/ibell/git/butsby/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:207: Phoenix.LiveView.Diff.write_component/4
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:553: Phoenix.LiveView.Channel.component_handle_event/6
(stdlib 4.3.1) gen_server.erl:1123: :gen_server.try_dispatch/4
(stdlib 4.3.1) gen_server.erl:1200: :gen_server.handle_msg/6
(stdlib 4.3.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
(ash_phoenix 1.2.13) lib/ash_phoenix/form/form.ex:1646: AshPhoenix.Form.submit/2
(ash_phoenix 1.2.13) lib/ash_phoenix/form/form.ex:1666: AshPhoenix.Form.submit!/2
(butsby 0.1.0) lib/butsby_web/components/forms.ex:75: ButsbyWeb.Components.Forms.handle_event/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:630: anonymous fn/4 in 3
[error] GenServer #PID<0.3292.0> terminating
** (Ash.Error.Unknown) Unknown Error

* []
(elixir 1.14.4) lib/enum.ex:1658: Enum."-map/2-lists^map/1-0-"/2
(ash 2.9.5) lib/ash/error/error.ex:207: Ash.Error.to_error_class/2
(ash_phoenix 1.2.13) lib/ash_phoenix/form/form.ex:1646: AshPhoenix.Form.submit/2
(ash_phoenix 1.2.13) lib/ash_phoenix/form/form.ex:1666: AshPhoenix.Form.submit!/2
(butsby 0.1.0) lib/butsby_web/components/forms.ex:75: ButsbyWeb.Components.Forms.handle_event/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:630: anonymous fn/4 in Phoenix.LiveView.Channel.inner_component_handle_event/4
(telemetry 1.2.1) /home/ibell/git/butsby/deps/telemetry/src/telemetry.erl:321: :telemetry.span/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/diff.ex:207: Phoenix.LiveView.Diff.write_component/4
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:553: Phoenix.LiveView.Channel.component_handle_event/6
(stdlib 4.3.1) gen_server.erl:1123: :gen_server.try_dispatch/4
(stdlib 4.3.1) gen_server.erl:1200: :gen_server.handle_msg/6
(stdlib 4.3.1) proc_lib.erl:240: :proc_lib.init_p_do_apply/3
(ash_phoenix 1.2.13) lib/ash_phoenix/form/form.ex:1646: AshPhoenix.Form.submit/2
(ash_phoenix 1.2.13) lib/ash_phoenix/form/form.ex:1666: AshPhoenix.Form.submit!/2
(butsby 0.1.0) lib/butsby_web/components/forms.ex:75: ButsbyWeb.Components.Forms.handle_event/3
(phoenix_live_view 0.18.18) lib/phoenix_live_view/channel.ex:630: anonymous fn/4 in 3
ZachDaniel
ZachDaniel•2y ago
šŸ¤”
WIGGLES
WIGGLESOP•2y ago
Which wasn't very helpful.
ZachDaniel
ZachDaniel•2y ago
yeah that looks less than ideal šŸ˜†
WIGGLES
WIGGLESOP•2y ago
Would posting the resources help?
ZachDaniel
ZachDaniel•2y ago
potentially... lets try a couple things first
WIGGLES
WIGGLESOP•2y ago
defmodule Butsby.Communities.Poll do
use Ash.Resource,
authorizers: [Ash.Policy.Authorizer],
data_layer: AshPostgres.DataLayer

alias Butsby.Communities.{Community, PollAnswer, PollResponse}

attributes do
uuid_primary_key :id
attribute :name, :string
attribute :starts, :utc_datetime
attribute :finishes, :utc_datetime
end

actions do
defaults [:create, :destroy]

read :read do
primary? true
pagination offset?: true, keyset?: true, required?: false
end
end

relationships do
belongs_to :community, Community do
allow_nil? false
attribute_writable? true
end

has_many :answers, PollAnswer do
could_be_related_at_creation? true
end

has_many :responses, PollResponse
end

postgres do
table "poll"
repo Butsby.Repo

references do
reference :community, on_delete: :delete
end
end

policies do
policy always() do
authorize_if always()
end
end
end
defmodule Butsby.Communities.Poll do
use Ash.Resource,
authorizers: [Ash.Policy.Authorizer],
data_layer: AshPostgres.DataLayer

alias Butsby.Communities.{Community, PollAnswer, PollResponse}

attributes do
uuid_primary_key :id
attribute :name, :string
attribute :starts, :utc_datetime
attribute :finishes, :utc_datetime
end

actions do
defaults [:create, :destroy]

read :read do
primary? true
pagination offset?: true, keyset?: true, required?: false
end
end

relationships do
belongs_to :community, Community do
allow_nil? false
attribute_writable? true
end

has_many :answers, PollAnswer do
could_be_related_at_creation? true
end

has_many :responses, PollResponse
end

postgres do
table "poll"
repo Butsby.Repo

references do
reference :community, on_delete: :delete
end
end

policies do
policy always() do
authorize_if always()
end
end
end
defmodule Butsby.Communities.PollAnswer do
use Ash.Resource,
authorizers: [Ash.Policy.Authorizer],
data_layer: AshPostgres.DataLayer

alias Butsby.Communities.Poll

attributes do
uuid_primary_key :id
attribute :label, :string
end

relationships do
belongs_to :poll, Poll do
allow_nil? false
attribute_writable? true
end
end

actions do
defaults [:create, :read]
end

postgres do
table "poll_answer"
repo Butsby.Repo
end

policies do
policy always() do
authorize_if always()
end
end
end
defmodule Butsby.Communities.PollAnswer do
use Ash.Resource,
authorizers: [Ash.Policy.Authorizer],
data_layer: AshPostgres.DataLayer

alias Butsby.Communities.Poll

attributes do
uuid_primary_key :id
attribute :label, :string
end

relationships do
belongs_to :poll, Poll do
allow_nil? false
attribute_writable? true
end
end

actions do
defaults [:create, :read]
end

postgres do
table "poll_answer"
repo Butsby.Repo
end

policies do
policy always() do
authorize_if always()
end
end
end
ZachDaniel
ZachDaniel•2y ago
step 1. mix hex.outdated to check for any ash packages out of date and then mix deps.update ash ash_phoenix ... for whichever packages could use an upgrade
WIGGLES
WIGGLESOP•2y ago
Yeah, let me make sure nothing is out of date. I see that quite a few are a couple of minor versions behind.
ZachDaniel
ZachDaniel•2y ago
thats me releasing new features/fixes šŸ˜†
WIGGLES
WIGGLESOP•2y ago
Okay, so I updated all my packages that I could and reset my database and the issue persists.
ZachDaniel
ZachDaniel•2y ago
šŸ‘ šŸ¤” so one thing I'm noticing is that there is no call to manage_relationship in your poll resource action Shouldn't cause this issue but without that, these child forms won't actually do anything You pasted this in:
answers: [
type: :list,
resource: PollAnswer,
create_action: :create
]
answers: [
type: :list,
resource: PollAnswer,
create_action: :create
]
is PollAnswer properly aliased?
WIGGLES
WIGGLESOP•2y ago
yes
alias Communities.{Poll, PollAnswer}

attr :id, :string, required: true
attr :community_id, :string, required: false
attr :rest, :global, @rest_include

def poll_form(assigns) do
alias Communities.{Poll, PollAnswer}

attr :id, :string, required: true
attr :community_id, :string, required: false
attr :rest, :global, @rest_include

def poll_form(assigns) do
poll_form is the component that handles rendering and the configuration is handled.
ZachDaniel
ZachDaniel•2y ago
try this instead of submit! use submit which returns {:ok, poll} and {:error, new_form} are you seeing any warning level logs about missed errors? AshPhoenix.Form doesn't dump all error messages into the form for safety reasons. Only specific messages. And by default it logs a warning about errors it didn't display
WIGGLES
WIGGLESOP•2y ago
submit_errors: [poll_id: {"is required", []}] hmm Let me see if a call to manage_relationships resolves this. And no, no warning logs anywhere. I had to go in and actually look at the errors that were in the form.
ZachDaniel
ZachDaniel•2y ago
ah, yeah okay I see the issue here is what you likely actually want
argument :answers, {:array, :map}

change manage_relationship(:answers, type: :create)
argument :answers, {:array, :map}

change manage_relationship(:answers, type: :create)
and then for forms you want forms: [auto?: true] auto?: true will set appropriate context on the answer forms that they shouldn't require poll_id yet (because its not been created šŸ™‚ ) and it will derive the forms option from the manage_relationship call in the action
WIGGLES
WIGGLESOP•2y ago
okay that was way easier than I would've thought. thank you.
ZachDaniel
ZachDaniel•2y ago
🄳

Did you find this page helpful?