Skip to content

Bootstrap component helpers

Rui Nunes edited this page Mar 1, 2018 · 7 revisions

Here are some more simple examples of passing bootstrap options through simpleform inputs:

For each of the helper's below you will need to add

b.use component # component = :icon, :tooltip etc.

to config/initializer/simple_form_bootstrap.rb under the config.wrappers :bootstrap section

ex:

config.wrappers :bootstrap, tag: 'div', class: 'control-group', error_class: 'error' do |b|
    b.use :html5
    b.use :placeholder
    b.use :label
    b.use :tooltip # enable the tooltip example from below.
    b.wrapper tag: 'div', class: 'controls' do |ba|
      ba.use :icon # enable the icon example from below
      ba.use :input
      ba.use :error, wrap_with: { tag: 'span', class: 'help-inline' }
      ba.use :hint,  wrap_with: { tag: 'p', class: 'help-block' }
    end
  end
Input icons helper

You can invoke these with f.input :password, icon: "icon-eye-open"

Add this to your initializer (e.g. create a /config/initializers/simple_form_components.rb file):

module SimpleForm
  module Components
    module Icons
      def icon(wrapper_options = nil)
        return icon_class unless options[:icon].nil?
      end

      def icon_class
        icon_tag = template.content_tag(:i, '', class: options[:icon])
      end
    end
  end
end

SimpleForm::Inputs::Base.send(:include, SimpleForm::Components::Icons)

Tooltips helper

You can invoke these with f.input :holder_name, tooltip: "Must be as it appears in the BANK STATEMENT" OR f.input :holder_name, tooltip: ["bottom", "Must be as it appears in the BANK STATEMENT"]

Add this to your initializers:

module SimpleForm
  module Components
    module Tooltips
      def tooltip(wrapper_options = nil)
        unless tooltip_text.nil?
          input_html_options[:rel] ||= 'tooltip'
          input_html_options['data-toggle'] ||= 'tooltip'
          input_html_options['data-placement'] ||= tooltip_position
          input_html_options['data-trigger'] ||= 'focus'
          input_html_options['data-original-title'] ||= tooltip_text
          nil
        end
      end

      def tooltip_text
        tooltip = options[:tooltip]
        if tooltip.is_a?(String)
          tooltip
        elsif tooltip.is_a?(Array)
          tooltip[1]
        else
          nil
        end
      end

      def tooltip_position
        tooltip = options[:tooltip]
        tooltip.is_a?(Array) ? tooltip[0] : "right"
      end
    end
  end
end

SimpleForm::Inputs::Base.send(:include, SimpleForm::Components::Tooltips)

You will still need to initialize your controls with javascript:

$('body').tooltip({ selector: "[data-toggle~='tooltip']"})

Typeahead helper

You can invoke this with f.input :state, typeahead: STATES_ARRAY where STATES_ARRAY is a ruby array containing a list of states.

Add this to your initializers:

module SimpleForm
  module Components
    module Typeahead
      def typeahead(wrapper_options = nil)
        unless typeahead_source.empty?
          input_html_options['data-provide'] ||= 'typeahead'
          input_html_options['data-items'] ||= 5
          input_html_options['data-source'] ||= typeahead_source.inspect.to_s
          nil
        end
      end

      def typeahead_source
        tdata = options[:typeahead]
        return Array(tdata)
      end
    end
  end
end

SimpleForm::Inputs::Base.send(:include, SimpleForm::Components::Typeahead)

Pretty FILE input fields

Creates a much prettier version of the file input field, which looks absolutely at home on a bootstrap website.

Add this to your initializer:

module SimpleForm
  module Inputs
    class FileInput < Base
      def input
        idf = "#{lookup_model_names.join("_")}_#{reflection_or_attribute_name}"
        input_html_options[:style] ||= 'display:none;'

        button = template.content_tag(:div, class: 'input-append') do 
          template.tag(:input, id: "pbox_#{idf}", class: 'string input-medium', type: 'text') +
          template.content_tag(:a, "Browse", class: 'btn', onclick: "$('input[id=#{idf}]').click();")
        end

        script = template.content_tag(:script, type: 'text/javascript') do
          "$('input[id=#{idf}]').change(function() { s = $(this).val(); $('#pbox_#{idf}').val(s.slice(s.lastIndexOf('\\\\\\\\')+1)); });".html_safe
        end

        @builder.file_field(attribute_name, input_html_options) + button + script
      end
    end
  end
end