Thanks for this great hint to your code. I adopted some of your stuff and solved other things a bit differently, that I want to share here, too. And I have some feedback to your idea.
I needed to remove your form = %Form{}
match from
[...]
|> Enum.each(fn method ->
def unquote(method)(form, field, opts \\ [])
since you can also call this function with an atom instead of a form. You might adapt this as well.
I did not want to change anything of my code, so I created a new ViewHelper
:
defmodule MyApp.BootstrapHelpers do
defmacro __using__(_opts) do
quote do
import Phoenix.HTML
import Phoenix.HTML.Form, except: [text_input: 3, file_input: 3, email_input: 3, password_input: 3, textarea: 3, telephone_input: 3, number_input: 3, date_input: 3, date_select: 3, datetime_select: 3, select: 4, time_select: 3, time_input: 3, url_input: 3, multiple_select: 4, range_input: 3]
import Phoenix.HTML.Link
import Phoenix.HTML.Tag
import Phoenix.HTML.Format
import SportsConnected.BootstrapHelpers
end
end
[:text_input, :file_input, :email_input, :password_input, :textarea, :telephone_input, :number_input, :date_input, :date_select, :datetime_select, :time_select, :time_input, :url_input, :range_input]
|> Enum.each(fn method ->
def unquote(method)(form, field, opts \\ []) when is_atom(field) do
opts = add_is_invalid_to_invalid_input(form, field, opts)
elem(Code.eval_string("Phoenix.HTML.Form.#{Atom.to_string(elem(__ENV__.function, 0))}(form, field, opts)", [form: form, field: field, opts: opts]), 0)
end
end)
[:select, :multiple_select]
|> Enum.each(fn method ->
def unquote(method)(form, field, options, opts \\ []) when is_atom(field) do
opts = add_is_invalid_to_invalid_input(form, field, opts)
elem(Code.eval_string("Phoenix.HTML.Form.#{Atom.to_string(elem(__ENV__.function, 0))}(form, field, options, opts)", [form: form, field: field, options: options, opts: opts]), 0)
end
end)
defp add_is_invalid_to_invalid_input(form, field, opts) do
if !is_atom(form) && Keyword.has_key?(form.errors, field), do: Keyword.update(opts, :class, "is-invalid", &("#{&1} is-invalid")), else: opts
end
end
Of course, you need to change the import in your web.ex
from Phoenix.HTML
to your new module.