I have template code that looks like this:
<%= form_for @changeset, @action, fn f -> %>
<%= if Enum.any?(f.errors) do %>
<%= for {attr, message} <- f.errors do %>
<li><%= humanize(attr) %> <%= message %></li>
<% end %>
<% end %>
<% end %>
But no errors are printed even if the changeset contains errors. Here is the inspected form struct. Notice that the errors list is empty even though it was built from the changeset with errors.
%Phoenix.HTML.Form{data: %BlogPhoenix.Comment{__meta__: #Ecto.Schema.Metadata<:built, "comments">,
content: nil, id: nil, inserted_at: nil, name: nil, post_id: nil,
posts: #Ecto.Association.NotLoaded<association :posts is not loaded>,
updated_at: nil}, errors: [], hidden: [], id: "comment",
impl: Phoenix.HTML.FormData.Ecto.Changeset, index: nil, name: "comment",
options: [method: "post"],
params: %{"content" => nil, "name" => nil, "post_id" => "1"},
source: #Ecto.Changeset<action: nil, changes: %{},
errors: [name: {"can't be blank", [validation: :required]},
content: {"can't be blank", [validation: :required]}],
data: #BlogPhoenix.Comment<>, valid?: false>}
What is going on here? Shouldn't this errors list be populated?
Your changeset's :action is nil, which is what hides the errors (see source).
The Ecto.Changeset docs (under the "Changeset actions" headline) states:
For example, frameworks such as Phoenix uses the value of changeset.action to decide if errors should be shown or not on a given form.
The docs above suggest this approach:
changeset = User.changeset(%User{}, %{age: 42, email: "[email protected]"})
# Since we don't plan to call Repo.insert/2 or similar, we
# need to mimic part of its behaviour, which is to check if
# the changeset is valid and set its action accordingly if not.
if changeset.valid? do
... success case ...
else
changeset = %{changeset | action: :insert} # action can be anything
... failure case ...
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With