jQuery not being loaded in Webpack - javascript

I am in the process of moving my entire application.js application into smaller page bundles using SplitChunks. In my users/show.html.erb page I am using the following tag to import the specific chunk.
<%= javascript_packs_with_chunks_tag 'users/show' %>
From the looks of my source code when I inspect it there are several bundles included such as the application.js file that includes jquery like this...
import "bootstrap"
require("turbolinks").start()
require("#rails/activestorage").start()
require("channels")
require("jquery")
I am just testing the page to see if jquery is being loaded. My users/show.js code looks like this:
import "chartkick"
import "chart.js"
window.onload = function() {
if (window.jQuery) {
// jQuery is loaded
alert("Yeah!");
} else {
// jQuery is not loaded
alert("Doesn't Work");
}
}
When I load the page I do see a Doesn't Work alert pop up indicating that jQuery has not been loaded. I'm newer to webpack so perhaps I have some misconfiguration somewhere, but if jquery is being loaded at the application.js level, why would my other pack not be able to listen to use jquery? Is this a problem with the dependency graphs?
My environment is as follows:
environment.js
const { environment } = require('#rails/webpacker');
const webpack = require('webpack');
environment.plugins.append('Provide', new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
Popper: ['popper.js', 'default']
}));
const config = environment.toWebpackConfig();
config.resolve.alias = {
jquery: 'jquery/src/jquery'
};
environment.splitChunks()
module.exports = environment;

I don't see where you add jQuery alias to your global (window) object. So you have to add it as below:
global.jQuery = jQuery; // This is a alias you defined in `ProvidePlugin`;
// window.jQuery = jQuery // also works
// Or you can add directly via your required object
const jquery = require('jquery');
global.jQuery = jquery;

I invariably get this issue and here is the two lines which makes it working for me
// https://stackoverflow.com/q/54905026/398863
window.jQuery = $;
window.$ = $;

Related

Bootstrap tooltip is not a function, Popper not working

I'm trying to use separate modules of bootstrap in my website instead of include the whole minified file. But I'm freaking out, why is that so complicated? Or I'm complicating this?
"devDependencies": {
"exports-loader": "1.1.1",
"webpack": "4.39.2",
"uglify-js": "3.6.0",
},
"dependencies": {
"bootstrap": "4.3.1",
"jquery": "3.4.1",
"popper.js": "1.14.7",
}
custom bootstrap.js in /js
/* Tries:
import $ from 'jquery';
import 'popper.js';
import 'popper.js/dist/umd/popper.js';
import 'popper.js/dist/umd/popper.min.js';
import 'bootstrap/dist/js/bootstrap.min.js'; */
window.jQuery = $;
window.$ = $;
global.$ = $;
/* BOOTSTRAP CUSTOM IMPORTS */
import 'bootstrap/js/dist/util';
import 'bootstrap/js/dist/alert';
import 'bootstrap/js/dist/button';
import 'bootstrap/js/dist/collapse';
import 'bootstrap/js/dist/dropdown';
import 'bootstrap/js/dist/modal';
import 'bootstrap/js/dist/tooltip';
import 'bootstrap/js/dist/popover';
import 'bootstrap/js/dist/tab';
With that, my code compile with success but on chrome console this error appear
Uncaught TypeError: $(...).tooltip is not a function
If I include this on my webpack.config.js:
new webpack.ProvidePlugin({
$: 'jquery/src/jquery',
jQuery: 'jquery/src/jquery',
'window.jQuery': 'jquery/src/jquery',
Popper: ['popper.js', 'default'],
}),
The tooltip error is gone, but starts to do error on other libs, like:
//Error on chrome console
Uncaught TypeError: $(...).mask is not a function
My Loading order of JS is:
LIBS (A WEBPACK MERGED FILE WITH ALL OTHER LIBS, LIKE JQUERY, MASKS, SLICK...)
BOOTSTRAP
POLYFILL
Searching the internet I see that a lot of people are experiencing this problem but the solutions they present are not working for me.
Please, anybody can help me?
Thanks for responses.
I figured out what is going on, not really understanding why but, bootstrap imports with JQuery were causing conflicts in the use of jquery by plugins, so, I had to remove jquery imported from bootstrap file then include manually on another process of plugins file, like that:
/* BOOTSTRAP.js CUSTOM IMPORTS */
//removed jquery imports
import 'bootstrap/js/dist/util';
import 'bootstrap/js/dist/alert';
import 'bootstrap/js/dist/button';
...
webpack.config:
//I had to maintain that provider
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
Popper: ['popper.js', 'default'],
}),
new MergeIntoSingleFilePlugin({
files: {
"js/libs.base.js": [
//included jquery min file on merge of plugins
path.join(source, 'src/libs/jquery', 'jquery-3.4.1.min.js'),
path.join(source, 'src/libs/jquery-mask', 'jquery.mask.min.js'),
...
I think this can help.
// TOOLTIP PLUGIN DEFINITION
// =========================
var old = $.fn.tooltip
$.fn.tooltip = function (option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.tooltip')
var options = typeof option == 'object' && option
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
if (typeof option == 'string') data[option]()
})

Bootstrap-notify with webpacker under Rails returning $.notify is not a function

I'm migrating a project from Sprockets to Webpacker.
One of the last thing I can't seem to get running correctly are notifications.
I used to be able to do : $.notify('Test') but now I'm getting
Uncaught TypeError: $.notify is not a function
I get the same error when I try to do this in the browser console, while before it worked fine.
This is my application.js file:
require("#rails/ujs").start();
require("turbolinks").start();
require("#rails/activestorage").start();
import 'bootstrap';
import 'bootstrap-notify';
I also tried require on bootstrap-notify but that doesn't make any difference.
Environments.js
const { environment } = require('#rails/webpacker')
const erb = require('./loaders/erb')
const coffee = require('./loaders/coffee')
const webpack = require('webpack');
environment.plugins.append('Provide', new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
jquery: 'jquery',
Popper: ['popper.js', 'default']
}));
environment.config.set('resolve.alias', {jquery: 'jquery/src/jquery'});
environment.loaders.prepend('coffee', coffee);
environment.loaders.prepend('erb', erb);
module.exports = environment;
If I put the bootstrap-notify.js file in the assets/javascripts folder and include it like this:
= javascript_include_tag 'bootstrap-notify', 'data-turbolinks-track': 'reload'
It works without any issue.
Finally got it working.
bootstrap-notify is an old package that doesn't do any export but just enables functions on $ ($.notify).
In order for this to play nice with Webpacker you can install script-loader
yarn add script-loader
And then add this to your application.js file (under webpack dir)
require("script-loader!bootstrap-notify");
This will evaluates the code in the global context. Make sure the code is minified because Webpack won't do that for you.

Rails 6 + Webpacker + jQuery + jGrowl is not working

I am using Rails 6. I am having problems with getting js plugins working. I am trying to add jGrowl.
This what I have tried:
yarn install jgrowl
This is how my application.js file looks like:
import 'jquery'
import 'jgrowl'
This is how my environment.js file looks like:
const { environment } = require('#rails/webpacker');
const webpack = require('webpack');
environment.plugins.append('Provide', new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}));
module.exports = environment;
What am I missing?
You need to initialize jQuery. Add the following code to application.js
import jQuery from 'jquery'
window.$ = jQuery
window.jQuery = jQuery

Bootstrap 4 Beta importing Popper.js with Webpack 3.x throws Popper is not a constructor

So Bootstrap 4 Beta is out... yey! However Tether has been replaced by Popper.js for tooltip (and other features). I saw an error thrown in the console fast enough to advise me of the change to Popper.js:
Bootstrap dropdown require Popper.js
Seems easy enough, I went and updated my webpack.config.js (the entire config can be seen here) and Bootstrap then started working (the only change I did was to replace Tether with Popper):
plugins: [
new ProvidePlugin({
'Promise': 'bluebird',
'$': 'jquery',
'jQuery': 'jquery',
'window.jQuery': 'jquery',
'window.$': 'jquery',
Popper: 'popper.js'
}),
I also did the import 'bootstrap' in my main.ts file.
However I now have another problem (which I did not have with Tether), a new error is thrown in the console:
Uncaught TypeError: Popper is not a constructor
If I try to debug in Chrome, I do have Popper loaded as an Object (which is why Bootstrap stopped complaining) as you can see in the print screen below.
Finally to include all my code. I use Bootstrap tooltip with a simple custom element built with Aurelia and TypeScript (which used to work with previous Bootstrap alpha 6 and Tether)
import {inject, customAttribute} from 'aurelia-framework';
import * as $ from 'jquery';
#customAttribute('bootstrap-tooltip')
#inject(Element)
export class BootstrapTooltip {
element: HTMLElement;
constructor(element: HTMLElement) {
this.element = element;
}
bind() {
$(this.element).tooltip();
}
unbind() {
$(this.element).tooltip('dispose');
}
}
Looks like I did not import Popper correctly, if so then what is the best way to achieve that with Webpack 3.x?
While browsing Bootstrap 4 documentation. I actually found a section about Webpack which explains how to install it correctly. Following the Bootstrap - installing with Webpack documentation, the answer is to simply modify the webpack.config.js with the following:
plugins: [
// ...
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
Popper: ['popper.js', 'default']
})
// ...
]
and let's not forget to import it in the main.ts
import 'bootstrap';
and voilĂ ! We are back in business :)
If you are using Webpack Do this:
window.$ = window.jQuery = require('jquery');
window.Popper = require('popper.js').default; // pay attention to "default"
require('bootstrap/dist/js/bootstrap');
In bootstrap": "^4.1.1" no need to import jquery and popper.js because those plugins will be already included when 'bootstrap' or bootstrap's plugins imported individually.
Notice that if you chose to import plugins individually, you must also
install exports-loader
No need to require files require('exports-loader?file ... '); as mentioned here because this will be taken care automatically by just installing $ npm install exports-loader --save-dev
import 'bootstrap'; // Import all plugins at once
//
// Or, import plugins individually
//
// import 'bootstrap/js/src/alert';
// import 'bootstrap/js/src/button';
// import 'bootstrap/js/src/carousel';
// import 'bootstrap/js/src/collapse';
// import 'bootstrap/js/src/dropdown';
// import 'bootstrap/js/src/modal';
// import 'bootstrap/js/src/popover';
// import 'bootstrap/js/src/scrollspy';
// import 'bootstrap/js/src/tab';
// import 'bootstrap/js/src/tooltip';
// import 'bootstrap/js/src/util';
There is no need to do anything like below:
const webpack = require('webpack');
module.exports = {
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
Popper: ['popper.js', 'default']
})
]
}
}
I am a vue.js developer and in new vue-cli-3, we create vue.config.js in root and place code like above to register new plugin, but as said there is no need to do all this in bootstrap": "^4.1.1".
Bootstrap's tooltip plugin is depend on popper.js and need to be enabled manually, so you can do like below in the component where you use tooltip element:
<script>
import $ from 'jquery';
export default {
mounted() {
$('[data-toggle="tooltip"]').tooltip();
},
};
</script>
I just ran into the same issue, and the solution is described here: https://github.com/FezVrasta/popper.js/issues/287
My main.ts now looks like something like the following:
import "jquery";
import Popper from "popper.js";
(<any>window).Popper = Popper;
require("bootstrap");
And I had to run npm install #types/requirejs --save to get the call to require working.
EDIT: I totally missed this the first time around, but the documention actually has a better way to solve this https://getbootstrap.com/docs/4.0/getting-started/webpack/
plugins: [
...
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
Popper: ['popper.js', 'default'],
// In case you imported plugins individually, you must also require them here:
Util: "exports-loader?Util!bootstrap/js/dist/util",
Dropdown: "exports-loader?Dropdown!bootstrap/js/dist/dropdown",
...
})
...
]
In ASP.net Core 2 project add the following scripts to of main HTML file ("_Layout.cshtml" file)
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/js/popper.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.min.js"></script>
For me it's working.

RequireJS is not loading modules relative to the baseUrl

In the <head> tag
<script>
var require = {
baseUrl: '/dist/js',
paths: {
jquery: 'jquery-1.11.3'
}
};
</script>
<script data-main="main.js" src="/dist/js/require.js></script>
And in main.js:
define(["exports", "jquery", "order.js", "search.js"], function (exports, _jquery, _orderJs, _searchJs) {
"use strict";
console.log("Hello");
});
Now, main.js loads just fine, same with jquery. But order.js and search.js is being loaded from the root (http://example.com/order.js).
Why is it not loading from the baseUrl?
Remove the .js extension from the module names you give to define or require. If you put the extension yourself, then RequireJS assumes the module name is a literal path and will skip your configuration.

Categories

Resources