marcamillion
marcamillion

Reputation: 33775

Tooltip component doesn't work with Simple Form and Bootstrap

I followed these instructions carefully: https://github.com/plataformatec/simple_form/wiki/Bootstrap-component-helpers

But the issue I keep getting is whenever my page loads, I get this JS error in my browser console:

Uncaught TypeError: undefined is not a function

Around this line:

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

I believe it is the .tooltip that is causing the issue, because the initializer seem to be working. I can tell because the generated html has the data-toggle attributes that are required for the JS selector.

I am using the bootstrap-sass gem.

Here is my simple_form_bootstrap initializer:

SimpleForm.setup do |config|
  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

    b.wrapper tag: 'div', class: 'controls' do |ba|
      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

  # Truncated for brevity

  config.default_wrapper = :bootstrap
end

Here is my simple_form_components.rb initializer:

module SimpleForm 
  module Components
    module Tooltips
      def tooltip
        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]
        tooltip.is_a?(String) ? tooltip : tooltip.is_a?(Array) ? tooltip[1] : nil
      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)

I called it like this in my _form.html.erb:

<%= f.input :title, placeholder: "Enter Title", tooltip: ["bottom", "Must be as it appears in the BANK STATEMENT"] %>

This is my post.js - also truncated for brevity:

$(document).ready(function () {
    $('#count').click(counter);
    $('#post_body, #post_title').on('change keydown keypress keyup blur focus', counter);
        $('body').tooltip({ selector: "[data-toggle~='tooltip']"});
});

This is the top part of my application.js:

//= require jquery
//= require jquery_ujs
//= require jquery.turbolinks
//= require bootstrap
//= require bootstrap/dropdown
//= require bootstrap/modal
//= require bootstrap/tooltip
//= require turbolinks
//= require_tree .

Upvotes: 1

Views: 959

Answers (1)

kross
kross

Reputation: 3752

The simple_form initializer code you are using is for bootstrap2, for bootstrap3 you may want to use:

# https://gist.github.com/mattclar/6315955#file-simple_form-rb
# http://stackoverflow.com/questions/14972253/simpleform-default-input-class
# https://github.com/plataformatec/simple_form/issues/316

inputs = %w[
  CollectionSelectInput
  DateTimeInput
  FileInput
  GroupedCollectionSelectInput
  NumericInput
  PasswordInput
  RangeInput
  StringInput
  TextInput
]
# DatepickerInput

inputs.each do |input_type|
  superclass = "SimpleForm::Inputs::#{input_type}".constantize

  new_class = Class.new(superclass) do
    def input_html_classes
      super.push('form-control')
    end
  end

  Object.const_set(input_type, new_class)
end

# Use this setup block to configure all options available in SimpleForm.
SimpleForm.setup do |config|

  config.boolean_style = :nested
  config.label_class = 'control-label'

  config.wrappers :overrides, tag: 'div', class: 'form-group', error_class: 'has-error',
                  defaults: { input_html: { class: 'default_class' } } do |b|

    b.use :html5
    b.use :min_max
    b.use :maxlength
    b.use :placeholder

    b.optional :pattern
    b.optional :readonly

    b.use :label_input
    b.use :hint,  wrap_with: { tag: 'span', class: 'help-block' }
    b.use :error, wrap_with: { tag: 'span', class: 'help-block has-error' }
  end

  config.wrappers :prepend, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
    b.use :html5
    b.use :placeholder
    b.wrapper tag: 'div', class: 'controls' do |input|
      input.wrapper tag: 'div', class: 'input-group' do |prepend|
        prepend.use :label , class: 'input-group-addon' ###Please note setting class here fro the label does not currently work (let me know if you know a workaround as this is the final hurdle)
        prepend.use :input
      end
      input.use :hint,  wrap_with: { tag: 'span', class: 'help-block' }
      input.use :error, wrap_with: { tag: 'span', class: 'help-block has-error' }
    end
  end

  config.wrappers :append, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
    b.use :html5
    b.use :placeholder
    b.wrapper tag: 'div', class: 'controls' do |input|
      input.wrapper tag: 'div', class: 'input-group' do |prepend|
        prepend.use :input
        prepend.use :label , class: 'input-group-addon' ###Please note setting class here fro the label does not currently work (let me know if you know a workaround as this is the final hurdle)
      end
      input.use :hint,  wrap_with: { tag: 'span', class: 'help-block' }
      input.use :error, wrap_with: { tag: 'span', class: 'help-block has-error' }
    end
  end

  # Wrappers for forms and inputs using the Twitter Bootstrap toolkit.
  # Check the Bootstrap docs (http://getbootstrap.com/)
  # to learn about the different styles for forms and inputs,
  # buttons and other elements.
  config.default_wrapper = :overrides
  SimpleForm.browser_validations = false
end

This may get you closer...

Upvotes: 1

Related Questions