Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bootstrap 4 "input-group-append" validation showing in two lines #762

Closed
viktorsmari opened this issue Aug 4, 2019 · 2 comments
Closed
Labels

Comments

@viktorsmari
Copy link

viktorsmari commented Aug 4, 2019

Using Rails 5.2, and Bootstrap 4.3.1 (and no gems like simple form etc).

input-group-append input-group-prepend are not working properly.

How can we change the initializer settings so this works properly with Bootstrap input-groups?

https://getbootstrap.com/docs/4.3/components/input-group/

2019-08-04_10-02-23

<div class="field_with_errors"><label for="material_price">Price</label></div>
<div class="input-group">
    <div class="field_with_errors"><label for="material_price" class="message">can't be blank</label><input placeholder="Material price" label="false" class="form-control" tabindex="7" type="text" name="material[price]" id="material_price" data-validate="true"></div>
    <div class="input-group-append">
        <span class="input-group-text">$</span>
    </div>
</div>

#config/initializers/client_side_validations.rb

 ActionView::Base.field_error_proc = proc do |html_tag, instance|
   if html_tag =~ /^<label/
     %(<div class="field_with_errors">#{html_tag}</div>).html_safe
   else
     %(<div class="field_with_errors"><label for="#{instance.send(:tag_id)}" class="message">#{instance.error_message.first}</label>#{html_tag}</div>).html_safe
   end
 end

Related to #617

@tagliala
Copy link
Contributor

tagliala commented Aug 4, 2019

Hi,

thanks for being part of the Client Side Validations community.

How can we change the initializer settings so this works properly with Bootstrap input-groups?

My general advise is to keep things as standard as possible with forms. There is plenty of edge cases, like this one.

Rather than customizing the initializer, that is indeed needed for failed server-side validations, please use a custom javascript like the one provided by client_side_validations-simple_form

ClientSideValidations.formBuilders['ActionView::Helpers::FormBuilder'] =
  add: (element, settings, message) ->
    @wrapper(settings.wrapper).add.call(@, element, settings, message)
  remove: (element, settings) ->
    @wrapper(settings.wrapper).remove.call(@, element, settings)
  wrapper: (name) ->
    @wrappers[name] || @wrappers.default

  wrappers:
    default:
      add: (element, settings, message) ->
        errorTag       = settings.error_tag or 'div'
        wrapperElement = element.parent()
        errorElement   = wrapperElement.find("#{errorTag}.invalid-feedback")

        unless errorElement.length
          errorElement = $("<#{errorTag}/>", { class: 'invalid-feedback', text: message })
          hintElement = wrapperElement.find('.form-text')

          if hintElement.length
            hintElement.before errorElement
          else
            wrapperElement.append errorElement

        element.addClass 'is-invalid'
        errorElement.text message

      remove: (element, settings) ->
        errorTag       = settings.error_tag or 'div'
        wrapperElement = element.parent()
        errorElement   = wrapperElement.find("#{errorTag}.invalid-feedback")

        element.removeClass 'is-invalid'
        errorElement.remove()

This also supports hint messages.

By the way, you will lose the right border radius on the append button

image

because of a Bootstrap issue.

There are workarounds (set wrapperElement as the closest form-group of the input, create a custom css class like .form-group-invalid, edit the above JavaScript to set the aforementioned css class to the wrapperElement, and force display of .invalid-feedback if it is present inside that class)

Ref:

Hope it helps

Closing here

@tagliala
Copy link
Contributor

tagliala commented Aug 4, 2019

About the initializer...

To show a proper validation message, if validations fail on the server side and you need to use input-groups, this is a working approach:

config/initializers/client_side_validations.rb

ActionView::Base.field_error_proc = proc do |html_tag, instance|
  html_tag.html_safe
end

Form field

<div class="form-group">
  <%= f.label :price %>
  <div class="input-group mb-3">
    <%= f.text_field :price, class: "form-control #{@metal.errors[:price].present? ? 'is-invalid': ''}" %>
    <div class="input-group-append">
      <span class="input-group-text" id="basic-addon2">$</span>
    </div>
    <%- if @metal.errors[:price].present? %>
      <div class="invalid-feedback"><%= @metal.errors[:price].first %></div>
    <% end %>
  </div>
</div>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants