flp

flp

Bootstrap requires since Bootstrap 4.0 is-invalid as field class to display the field error.
I found a solution presented in the following to display the errors again, but I don’t really know what’s the best way to integrate it. I add for each field with errors in a generic way the is_invalid class.

def password_input(form, field, opts \\ []) do
  opts = if !is_atom(form) && Keyword.has_key?(form.errors, field), do: Keyword.update(opts, :class, "is-invalid", &("#{&1} is-invalid")), else: opts
  ...

I wonder now how I can integrate this in the best way into the Phoenix.HTML helpers with touching them as least as possible, so I hopefully have the least trouble to stay up to date with the helpers.

In a way like this to just not import the functions I need to “override”?

Showing Posts 1 to 4

drl123

drl123

I haven’t tried it yet, but expect I’m going to be in the same boat as you with a side project I’m starting that is planned to use BS 4. There haven’t been updates to this in a while, but if the BS markup hasn’t changed, it may not need any.

https://github.com/GBH/phoenix_bootstrap_form

flp

flp OP

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.

gorav

gorav

I follow the following:

  def input(form, field, opts \\ []) do
  ...
  opts =
      put_in(
        opts[:class],
        String.trim("form-control #{input_state_class(form, field)} #{opts[:class]}")
      )
  ...
  end

and

  def input_state_class(form, field) do
    cond do
      # The form was not yet submitted
      !form.source.action ->
        ""

      form.errors[field] ->
        "is-invalid"

      true ->
        "is-valid"
    end
  end
— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews