lifeofdan
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.
Trending in Questions
Hello!
Suppose you are building workflow (order / task / payment) processing system with the following requirements:
Each workflow con...
New
I’m aware of 2 such projects, are there others?
git: GitHub - team-alembic/realworld: A fullstack Phoenix LiveView application with back...
New
Hi everyone.
My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
I really like the adapter patterns that ecto, nebulex, waffle, etc. use and would love find something similar for a key management servic...
New
Hello folks!
So at work, we are seeing some situations where we have to define some “fixed” strings that are used across the codebase in...
New
How Can I Optimise Compile Time Dependencies
I have been building an elixir application for about 2 years now. Many modules and files ha...
New
Hi,
we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New
Other Trending Topics
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
There has been a thread to discuss the Stack Overflow Developer Survey on this forum every year since 2018, so here’s yet another one for...
New
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself.
My main conc...
New
I love Elixir. It’s one of 2 programming languages I’ve ever fallen in love with.
But I don’t use it anymore.
Serverless was the promis...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #ai
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #blog-post
- #elixirconf-us
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #elixirconf-eu
- #api
- #forms
- #security
- #hex










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
zachdaniel
Hmm…I think there was a recent change that only shows errors on touched fields, could that be part of the error that you’re seeing? There would be some code in your core components file like
If you remove that and just do
errors = field.errors, does it behave more as you’d expect?lifeofdan
Thank you! This doesn’t exactly give me the behaviour that I want but it puts me exactly where I need to be to get what I want. Thank you so much, I knew it had to be something simple like this!
zorn
Yup.
This replaces the
phx-feedback-forlogic. You can toggle the docs for the pre-rc versions to see those docs to compare.axelson
Also it’s worth mentioning that the released version (i.e. non-RC) of
mix phx.newwill create apps using an RC version of phoenix live view and also specifically include theerrors = if Phoenix.Component.used_input?(field), do: field.errors, else: []line.carlgleisner
Hi @lifeofdan, could you please elaborate on how you went from there?
There was a short exchange about this on the Discord as well but I can’t see that there were any conclusions documented.
I’m setting up a little example for myself now that I’m planning to share, but I thought that maybe you’re sitting on (way better) insights that might benefit the greater community.
Thanks in advance
zachdaniel
There is some interesting behavior here, and using a repro from @carlgleisner I’ve ultimately decided to open a bug on LiveView. I could be wrong, it could be something wrong with
AshPhoenix.Form, but I have not been able to identify what that would be.lifeofdan
@carlgleisner I found the entire process quite frustrating to be honest. In order to get the behaviour I wanted I ended up just handling everything myself. I used
AshPhoenix.Formto do the actual form field validation but otherwise I threw the errors and all of that myself because I couldn’t get the defaults to work the way I expected. Below is the code I used to get the behaviour I wanted. Take this with a very large grain of salt as this is my first time using phoenix forms and I could just be doing something wrong. The main things you will notice here is that I’m not usingfor={@form}or anyfield={@form[:name]}on the inputs. I’m just handling everything myself and not using any helpers because I just couldn’t get what I wanted otherwise. Below are my two relevant files, the form and the ash resource.Ash Resource
zachdaniel
Hey there! So this was actually confirmed to be a bug in live_view, that is fixed in the latest
main.Link: Changing conditions of `Component.used_input?` not resulting in a rerender of form fields · Issue #3460 · phoenixframework/phoenix_live_view · GitHub
zachdaniel
It’s also worth mentioning that you are technically using a release candidate of phoenix_live_view.
Although… the latest installer does in fact use that release candidate automatically, so it does kind of feel like its what they’re pushing people to do… for all intents and purposes, given that the installer installs the release candidate, it seems like 1.0.0-rc.* is the defacto “current latest version”
lifeofdan
I checked out
. Thanks to all those who continued to follow this up even after I had decided to just go my own way.
mainand it does now, indeed, work as expected. (once I un-delete theerrors = if Phoenix.Component.used_input?(field), do: field.errors, else: []). Now I can delete a ton of codeIt is also interesting that this bugfix was merged into
mainon Sept 9th but still hasn’t been put into a release yet. This seems like something that everyone would be running into at the moment if they have initialized a new project. Glad it is fixed though, and I guess I will run onmainbranch until this is merged into a release.