Hi,
I’m having some difficulty figuring out how to implement the following: I have the following resources:
defmodule WedEvents.Events.Invitation do
actions do
defaults [:read, :destroy, :update]
default_accept [:invitation_code, :event_id]
create :create do
primary? true
argument :invitation_users, {:array, :map}, allow_nil?: false
change relate_actor(:created_by)
change manage_relationship(:invitation_users, type: :create)
end
end
attributes do
uuid_primary_key :id
attribute :invitation_code, :string
timestamps()
end
relationships do
belongs_to :event, WedEvents.Events.Event
belongs_to :created_by, WedEvents.Accounts.User, allow_nil?: false
has_many :invitation_users, WedEvents.UserEvents.InvitationUser,
destination_attribute: :invitation_id
end
{...other fields}
end
defmodule WedEvents.UserEvents.InvitationUser do
actions do
defaults [:read, :destroy, :update]
default_accept [:role, :invitation_id, :user_id]
create :create do
primary? true
change relate_actor(:created_by)
change relate_actor(:updated_by)
end
end
attributes do
uuid_primary_key :id
attribute :role, :string, allow_nil?: false, default: "guest"
timestamps()
end
relationships do
belongs_to :created_by, WedEvents.Accounts.User, allow_nil?: false
belongs_to :updated_by, WedEvents.Accounts.User, allow_nil?: false
belongs_to :invitation, WedEvents.Events.Invitation, allow_nil?: false
belongs_to :user, WedEvents.Accounts.User, allow_nil?: false
has_one :rsvp, WedEvents.UserEvents.RSVP
end
end
I have the following live component:
defmodule WedEventsWeb.InvitationLive.FormComponent do
use WedEventsWeb, :live_component
alias WedEvents.Events
alias WedEvents.Accounts
@impl true
def render(assigns) do
~H"""
<div>
<.header>
<%= @title %>
<:subtitle>Use this form to manage invitation records in your database.</:subtitle>
</.header>
<.simple_form
for={@form}
id="invitation-form"
phx-target={@myself}
phx-change="validate"
phx-submit="save"
>
<.input field={@form[:invitation_code]} label="Invitation Code" />
<.input field={@form[:event_id]} type="select" label="Event" options={@events} />
<.input field={@form[:user_ids]} type="select" label="Guests" options={@users} multiple />
<:actions>
<.button phx-disable-with="Saving...">Save Invitation</.button>
</:actions>
</.simple_form>
</div>
"""
end
@impl true
def update(assigns, socket) do
{:ok, events} = Events.Event |> Ash.read()
{:ok, users} = Accounts.User |> Ash.read()
event_options = Enum.map(events, &{&1.title, &1.id})
user_options = Enum.map(users, &{&1.email, &1.id})
form =
case assigns.action do
:new ->
AshPhoenix.Form.for_create(Events.Invitation, :create,
actor: assigns.current_user,
forms: [auto?: true]
)
:edit ->
AshPhoenix.Form.for_update(assigns.invitation, :update,
actor: assigns.current_user,
forms: [auto?: true]
)
end
IO.inspect(form, label: "form")
{:ok,
socket
|> assign(assigns)
|> assign(:form, to_form(form))
|> assign(:events, event_options)
|> assign(:users, user_options)}
end
@impl true
def handle_event("validate", %{"form" => invitation_params}, socket) do
form =
AshPhoenix.Form.validate(socket.assigns.form, invitation_params)
{:noreply, assign(socket, form: form)}
end
def handle_event("save", %{"form" => invitation_params}, socket) do
save_invitation(socket, socket.assigns.action, invitation_params)
end
defp save_invitation(socket, :edit, invitation_params) do
invitation_users =
Enum.map(invitation_params["user_ids"], fn user_id ->
%{user_id: user_id, invitation_id: socket.assigns.form.data.id}
end)
# How to add invitation_users to invitation_params?
invitation_params = Map.put(invitation_params, "invitation_users", invitation_users)
IO.inspect(invitation_params, label: "invitation_params")
case AshPhoenix.Form.submit(socket.assigns.form,
params: invitation_params,
action_opts: [load: [:event, :invitation_users]]
) do
{:ok, invitation} ->
notify_parent({:saved, invitation})
{:noreply,
socket
|> put_flash(:info, "Invitation updated successfully")
|> push_patch(to: socket.assigns.patch)}
{:error, form} ->
{:noreply, assign(socket, form: form)}
end
end
defp save_invitation(socket, :new, invitation_params) do
case AshPhoenix.Form.submit(socket.assigns.form,
params: invitation_params,
action_opts: [load: [:event]]
) do
{:ok, invitation} ->
notify_parent({:saved, invitation})
{:noreply,
socket
|> put_flash(:info, "Invitation created successfully")
|> push_patch(to: socket.assigns.patch)}
{:error, form} ->
{:noreply, assign(socket, form: form)}
end
end
defp notify_parent(msg), do: send(self(), {__MODULE__, msg})
end
I am using forms?: auto
but it doesnt seem to generate a nested form for me to use. Ive tried manually creating the right data that gets passed to submit and it still doesnt create records for invitation_users. I know I’m probably not configuring things correctly but Ive run out of documentation or examples I can use on the internet
How would you have it such that I can add and remove guests (users) in my model from the invitation form? Or a nudge right direction would be awesome
Any help is much appreciated! Thank you!