I have a simple form with a textarea, where the user will type in (or copy'n'paste) a json string into it. The form will be sent to my controller action and I will validate the json string and if it will be ok, I will create some records and all is fine.
To send the form to my controller action I use Phoenix.HTML.Form "With connection data" at the moment and therefore I have no model/changeset.
<%= form_for @conn, @action, [as: :match], fn f -> %>
<%= textarea f, :json, rows: 20 %>
<%#= error_tag @changeset, f, :json %>
<% end %>
If the json is invalid for some reason, I like to render the form again and display the error message(s). error_tag
is a view helper method which will display an error at a field if there's a changeset. Because of this it's commented out now.
def error_tag(form, field) do
if error = form.errors[field] do
content_tag :span, (humanize(field) <> " " <> translate_error(error)), class: "help-block"
end
end
def error_tag(changeset, form, field) do
if changeset.action do
error_tag(form, field)
end
end
What is a proper way to add an error so that I can display them at a form field. Do I have to add the error to @conn
or f
(form) or Is there another way to got?
create a keyword list with the errors inside the action
errors = [field: "error message"]
then pass it when calling the render method
render(conn, "template.html", errors: errors)
add a helper function to extract and format the message from the keyword list
def error_tag(errors, field) when is_list(errors) and is_atom(field) do
case Keyword.fetch(errors, field) do
{:ok, message} -> content_tag :span, (humanize(field) <> " " <> translate_error(message)), class: "help-block"
:error -> html_escape("")
end
end
display the error message
<%= form_for @conn, @action, [as: :match], fn f -> %>
<%= textarea f, :json, rows: 20 %>
<%= error_tag @errors, :json %>
<% end %>
Another approach is to create an embeded_schema
in which you can define all the data model including validations without persisting into the DB, and rely on the validation/error management shipped in Phoenix. José Valim explains how to use this approach.
You just create the schema this way:
data = %{}
types = %{first_name: :string, last_name: :string, email: :string}
changeset =
{data, types} # The data+types tuple is equivalent to %Registration{}
|> Ecto.Changeset.cast(params["sign_up"], Map.keys(types))
|> validate_required(...)
|> validate_length(...)
and then show the errors as usual:
<%= error_tag f, :first_name %>
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