I have a "Select All" button that uses this code:
<script type='text/javascript'>
$('#check_all').on("click", function() {
$('input[type="checkbox"]').click();
});
</script>
Since I upgraded to Rails 6 + Webpacker, it stopped working. The console shows this error:
Uncaught ReferenceError: $ is not defined
I managed to fix it by altering environment.js
from:
environment.plugins.append('Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
Popper: ['popper.js', 'default']
})
)
To:
environment.plugins.append('Provide',
new webpack.ProvidePlugin({
$: 'jquery/src/jquery',
jQuery: 'jquery/src/jquery',
Popper: ['popper.js', 'default']
})
)
But once that's fixed, datatables breaks.
Any ideas how to have them both working together? Thanks!
Moving your own Javascript into the pack file was a good choice for maintainability. However, I'm guessing those are dynamically generated checkboxes. They may not exist when the bind runs. You can rise above the problem by binding to a parent element and using event delegation. document.body
is a common binding choice for delegated events with Turbolinks.
I'm not a fan of calling click() on a checkbox. The result isn't always consistent for users, and it fires off a bunch of unnecessary events in the browser. Inverting the checked
prop is cleaner and more consistent.
Getting DataTables to load as a module requires an import shim. It's an older package that prefers AMD over CommonJS and trips over itself in the Webpack environment. Fortunately, there's a standard fix for older code, using the imports-loader. Unfortunately, even then it's got a slightly strange factory export, into which you're expected to inject the window
and jQuery
variables. Fortunately it's also documented here.
Putting that all together, here's a suggested application.js
:
require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
import $ from 'jquery'
// Add DataTables jQuery plugin
require('imports-loader?define=>false!datatables.net')(window, $)
require('imports-loader?define=>false!datatables.net-select')(window, $)
// Load datatables styles
import 'datatables.net-dt/css/jquery.dataTables.css'
import 'datatables.net-select-dt/css/select.dataTables.css'
$(document).on('turbolinks:load', () => {
$(document.body).on('click', '#check_all', () => {
var checkBoxes = $('input[type="checkbox"]')
checkBoxes.prop("checked", !checkBoxes.prop("checked"))
})
// placeholder example for datatable with checkboxes
$('#example').DataTable({
columnDefs: [{
render: (data,type,row) => `<input type="checkbox" value="${row[0]}">`,
orderable: false,
targets: 0
}],
order: [[ 1, 'asc' ]]
})
})
You'll need to yarn add imports-loader
, since it's a Webpack option.
The ProvidePlugin is not required for any of this. Unless you're depending on it for injection of imports to third-party code, it can be safely removed.
run yarn add imports-loader
I use bootstrap4 datatable if you use bootstrap3 or other CSS frameworks, please follow the installation from this link: https://datatables.net/download/
in my config/webpack/loaders/datatable.js
module.exports = {
test: /datatables\.net.*/,
use: [{
loader: 'imports-loader?define=>false'
}]
}
in my config/webpack/environment.js
const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
const coffee = require('./loaders/coffee')
const datatable = require('./loaders/datatable')
environment.plugins.append('Provide', new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
jquery: 'jquery',
'window.jQuery': 'jquery',
Popper: ['popper.js', 'default']
}))
/**
* To use jQuery in views
*/
environment.loaders.append('expose', {
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: '$'
}]
})
environment.loaders.prepend('coffee', coffee)
environment.loaders.prepend('coffee', datatable)
module.exports = environment
in my app/javascript/packs/dashboard.js
require( 'jszip' );
require("datatables.net-bs4")(window, $);
require("datatables.net-responsive-bs4")(window, $);
require("datatables.net-buttons-bs4")(window, $);
require("datatables.net-select-bs4")(window, $);
require("datatables.net-bs4/css/dataTables.bootstrap4.css");
require("datatables.net-responsive-bs4/css/responsive.bootstrap4.css");
require("datatables.net-buttons-bs4/css/buttons.bootstrap4.min.css");
require("datatables.net-select-bs4/css/select.bootstrap4.css");
Feel free to user
import './datatable'
at any .js
file in app/javascript/packs
you like
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With