How to set an error class on form input fields, in case any validation fails

Hello,

phx-feedback-for does its job of hiding stuff until e.g. input field is used. But what I need is another mechanism that will add a CSS class (e.g. has-error) to an element if any validation fails for this specific field.

So required behavior would be to provide a visual feedback (red border around input, for example) whenever any of validations fail, and not just show the error messages below.

Any ideas? Thanks.

Welcome to the forum. ^^

Here is a blog post that helped me to create my own view style helpers for my Phoenix forms.

And this is a helper that may interrest you:

  defp state_class(class, form, field, opts) do
    cond do
      # no state checking
      opts[:no_state] -> class

      # The form doesn't have action key
      !Map.has_key?(form.source, :action) -> class

      # The form was not yet submitted
      !form.source.action -> class

      form.errors[field] -> "#{class} is-invalid"

      true -> "#{class} is-valid"
    end
    |> String.trim()
  end

Example of usage:

input @form, :name, class: state_class("blabla", @form, :name, [])

Edit:

You can simplify the above helper of course for your own needs. And to use it like that in your templates of course it needs not to be private. So instead of defp you will use def for it to be defined as a public function that you can import into your views. In my case I don’t call it directly that’s why it is private.

Thanks, it’s working fine. I somehow missed that article.

p.s. Thanks for the welcome! I’ve actually been programming in Elixir in the background for a few years but am only now exploring using it for actual production projects.

1 Like

You can copy error_tag from lib/my_app_web/views/error_helpers.ex and name it error_class like so:

  @doc """
  Adds error class for form input errors.
  """
  def error_class(form, field) do
    Enum.map(Keyword.get_values(form.errors, field), fn error ->
      "invalid-feedback"
    end)
  end

and then add it to your form like this:

<%= text_input f, :email, class: "#{error_class(f, :email)}" %>