8

I have tried changing the versions of bootstrap, jquery, and popper but no luck. I don't think I am using more than one version of jquery. Not sure where it went wrong. It would be great if someone helps me to find what I am missing.

Here is my list of files,

package.json:

{
  "name": "kf",
  "private": true,
  "dependencies": {
    "@fortawesome/fontawesome-free": "^5.12.1",
    "@rails/ujs": "^6.0.0",
    "@rails/webpacker": "4.2.2",
    "bootstrap": "^4.4.1",
    "jquery": "^3.4.1",
    "popper.js": "^1.16.1",
    "sweetalert2": "^9.8.2"
  },
  "version": "0.1.0",
  "devDependencies": {
    "webpack-dev-server": "^3.10.3"
  }
}

config/webpack/environment.js

const { environment } = require('@rails/webpacker');
const webpack = require('webpack');

environment.plugins.append(
  'Provide',
  new webpack.ProvidePlugin({
    $: 'jquery/src/jquery',
    jQuery: 'jquery/src/jquery',
    Popper: ['popper.js', 'default']
  })
);

module.exports = environment;

application.js

require('@rails/ujs').start();
require('jquery/dist/jquery');
require('popper.js/dist/umd/popper');
require('bootstrap/dist/js/bootstrap');
require('@fortawesome/fontawesome-free');
require('./owl.carousel.min');
require('./fastclick');
require('./custom-script');
require('./return-to-top');

const Swal = require('sweetalert2');
window.Swal = Swal;
const images = require.context('../images', true);
const imagePath = name => images(name, true);
import 'stylesheets/application';

jQuery(document).ready(function($) {
  $('[data-toggle="tooltip"]').tooltip();
});

Warning:

jQuery.Deferred exception: $(...).tooltip is not a function TypeError: $(...).tooltip is not a function

Error:

Uncaught TypeError: $(...).tooltip is not a function
Tony Ngo
  • 19,166
  • 4
  • 38
  • 60
Sri
  • 2,233
  • 4
  • 31
  • 55

4 Answers4

13

I have resolved by adding a custom.js in the webpack folder like in the webpack configuration git document:

https://github.com/rails/webpacker/blob/master/docs/webpack.md#configuration

#config/webpack/custom.js

module.exports = {
  resolve: {
    alias: {
      jquery: 'jquery/src/jquery'
    }
  }
};

And my config/webpack/environment.js changed to

const { environment } = require('@rails/webpacker');
const customConfig = require('./custom');
const webpack = require('webpack');

environment.plugins.append(
  'Provide',
  new webpack.ProvidePlugin({
    $: 'jquery/src/jquery',
    jQuery: 'jquery/src/jquery',
    Popper: ['popper.js', 'default']
  })
);
environment.config.merge(customConfig);

module.exports = environment;

Restart the server and the tooltip is working fine.

Note: You don't need to add the require('jquery'), require('popper') in the application.js

Sri
  • 2,233
  • 4
  • 31
  • 55
  • 1
    Worked for me at first but then when I tried to use a modal I got `$(...).modal is not a function`. I solved it by commenting/removing the `$` and `jquery` keys inside webpack.ProvidePlugin(). I don't know the ins and outs of webpack but I suppose jQuery was being called again after bootstrap. Anyways, this helped a lot. Thanks! – Sergio Gonzalez Sep 06 '20 at 10:52
1

I think your webpack config should be like this

    new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery",
        Popper: ['popper.js', 'default']
    }),

Let me know if you still have any errors

Tony Ngo
  • 19,166
  • 4
  • 38
  • 60
  • 1
    Thanks for your suggestion Tony, but I modified to the above and got different error of `owl.carousel.min.js:6 Uncaught TypeError: Cannot read property 'fn' of undefined` – Sri Mar 01 '20 at 16:29
1

@Sri's answer worked for me. I just wanted to add that I needed this in application.js

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

require('jquery')
require('popper.js')

window.$ = window.jQuery = require("jquery");
import "bootstrap/dist/js/bootstrap.bundle.js"

document.addEventListener("turbolinks:load", () => {
  $('[data-toggle="tooltip"]').tooltip();
  $('[data-toggle="popover"]').popover()
})

And this in the view:

<button type="button" class="btn btn-secondary" data-toggle="tooltip" data-placement="top" title="Tooltip on top">
  Tooltip on top
</button>
stevec
  • 41,291
  • 27
  • 223
  • 311
0

The underlying issue is that tooltip() has not always existed in jQuery UI. It was added in version 1.9. Proof:

version added: 1.9 (Source: API.jQueryUI.com: Tooltip Widget.)

If you don't have a version of jQuery UI at version 1.9 or higher, you'll get the error: tooltip() is not a function().

Don't forget, by upgrading your jQuery/jQuery UI version, you may also introduce other errors, for instance, “Uncaught TypeError: a.indexOf is not a function”, but these are fixed easily just by searching for the solutions to each and fixing them. This is the general procedure in upgrading any package you use, sometimes things break, but they are always fixable. Using up-to-date code is your best ally in package management.

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133