Correct placement of methods used in phoenix template

Using default text_input I would like to add an “invalid” or “valid” class dynamically based on the populated changeset. This is something I really would like defined in a re-usable way, but I’m a little cloudy on where I should put the code.

def materialized_input(form, field, opts \\ []) do
   if form[:errors][field] do
     v = [class: :invalid]
   else
     v = [class: :valid]
  end
  text_input(form, field, opts ++ v)
end

Where would this function best be placed?

I think this actually solved it!

1 Like

Final form helper module:

Here was the final form helper module:


  @doc """
  Returns a keyword list with the specified class value appended
  """
  defp opts_with_class_value(value, opts \\ []) do
      new_opts = case Keyword.fetch(opts, :class) do
        {:ok, c} -> Keyword.replace!(opts, :class, c <> " #{value}")
        _ -> Keyword.put_new(opts, :class, " #{value}")
      end
      IO.inspect(new_opts)
      new_opts
  end

  @doc """
  Returns the options with a class value which indicates whether
  the control is valid or not.
  """
  defp opts_with_valid_class(has_err?, opts \\ []) do
    if has_err? > 0 do
      opts_with_class_value("invalid", opts)
    else
      IO.inspect(opts)
      opts
    end
  end

  @doc """
   Appends the class to a form input that is not valid
   for use with materialize.
  """
  def m_text_input(form, field, opts \\ []) do
    has_err = Enum.count(Keyword.get_values(form.errors, field))
    Phoenix.HTML.Form.text_input(form, field, opts_with_valid_class(has_err, opts))
  end```