I am having an issue where form field errors are not being displayed under the following scenario. Load the page, fill one field of the form, click “submit”. The errors are being shown on the struct but there is no error on the form fields. However, if you just reload the page and click submit without touching any of the inputs you get the “is required” errors. Validation on individual fields while filling out the form also works as expected. Here is my resource.
defmodule App.Public.Contact do
use Ash.Resource,
domain: App.Public,
authorizers: [Ash.Policy.Authorizer],
data_layer: AshPostgres.DataLayer,
extensions: [AshJsonApi.Resource]
require Ash.Expr
json_api do
type "contact"
end
postgres do
table "public_contacts"
repo App.Repo
end
actions do
defaults [:read, :destroy, update: :*]
create :send_message do
accept [:email, :message, :name]
validate match(
:email,
~r<^[a-zA-Z2-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$>
) do
message "invalid email"
end
end
end
policies do
policy action(:send_message) do
authorize_if always()
end
policy action_type(:read) do
authorize_if expr(^actor(:kind) == :manager)
end
end
attributes do
uuid_primary_key :id
attribute :email, :ci_string, allow_nil?: false, public?: true
attribute :message, :string, allow_nil?: false, public?: true
attribute :name, :string, allow_nil?: false, public?: true
create_timestamp :created_at
update_timestamp :updated_at
end
end
Here is my form
defmodule App.ContactLive do
use AppWeb, :live_view
@impl true
def render(assigns) do
~H"""
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 my-8">
<div class="text-gray-700">
<.simple_form id="contact-form" for={@form} phx-submit="submit" phx-change="validate">
<div class="grid sm:grid-cols-2 gap-10">
<div>
<.input
type="text"
class={@disabled_loading_state}
field={@form[:name]}
placeholder="John Doe"
label="Name"
/>
</div>
<div>
<.input
type="email"
class={@disabled_loading_state}
field={@form[:email]}
placeholder="john@example.com"
label="Email"
/>
</div>
</div>
<.input
class={@disabled_loading_state}
field={@form[:message]}
placeholder="Enter your message here..."
label="Message"
type="textarea"
/>
<:actions>
<.button phx-disable-with="Sending..." class="phx-submit-loading:cursor-not-allowed">
Submit
</.button>
</:actions>
</.simple_form>
</div>
<div class="mx-4 md:border-l border-gray-400 bg-gray-200 h-screen">
<div class="text-center mx-4 lg:mx-12 md:px-4 flex items-stretch">
<div class="md:h-72 relative">
<div class="relative md:top-1/2">
<h1 class="leading-none mb-16">We want to hear from you!</h1>
</div>
</div>
</div>
</div>
</div>
"""
end
@impl true
def mount(_params, _session, socket) do
form =
App.Public.Contact
|> AshPhoenix.Form.for_create(:send_message, as: "contact")
|> to_form()
disabled_loading_state =
"phx-submit-loading:cursor-not-allowed phx-submit-loading:bg-slate-50 phx-submit-loading:text-slate-500 phx-submit-loading:border-slate-200"
{:ok,
socket
|> assign(:disabled_loading_state, disabled_loading_state)
|> assign(:form, form)}
end
@impl true
def handle_event("validate", params, socket) do
validate = AshPhoenix.Form.validate(socket.assigns.form, params["contact"])
{:noreply, socket |> assign(form: validate)}
end
@impl true
def handle_event("submit", params, socket) do
case AshPhoenix.Form.submit(socket.assigns.form, params: params["contact"]) do
{:ok, form} ->
{:noreply,
socket
|> put_flash(:info, "Thank you for your message #{form.email}!")}
{:error, form} ->
{:noreply, socket |> assign(form: form)}
end
end
end
Is this expected behaviour or is this a bug? Also, is there a way I can manually take over this error behaviour when required? Any help appreciated, this is my first attempt using phoenix liveview so I accept I could be doing something wrong.
Thanks in advance.