简体   繁体   English

Rails 6 + Webpack、数据表、jQuery

[英]Rails 6 + Webpack, Datatables, jQuery

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.自从我升级到 Rails 6 + Webpacker 后,它就停止工作了。 The console shows this error:控制台显示此错误:

Uncaught ReferenceError: $ is not defined

I managed to fix it by altering environment.js from:我设法通过从以下位置更改environment.js来修复它:

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.将您自己的 Javascript 移动到包文件中是一个很好的可维护性选择。 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. document.body是使用 Turbolinks 的委托事件的常见绑定选择。

I'm not a fan of calling click() on a checkbox.我不喜欢在复选框上调用 click() 。 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.反转checked道具更干净,更一致。

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.这是一个较旧的包,它更喜欢 AMD 而不是 CommonJS,并且在 Webpack 环境中会自己绊倒。 Fortunately, there's a standard fix for older code, using the imports-loader .幸运的是,有一个针对旧代码的标准修复程序,使用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.不幸的是,即便如此,它也有一个稍微奇怪的工厂导出,您需要将windowjQuery变量注入其中。 Fortunately it's also documented here .幸运的是,这里也有记录

Putting that all together, here's a suggested application.js :综上所述,这是一个建议的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.您需要使用yarn add imports-loader ,因为它是一个 Webpack 选项。

The ProvidePlugin is not required for any of this.任何这些都不需要 ProvidePlugin。 Unless you're depending on it for injection of imports to third-party code, it can be safely removed.除非您依赖它来向第三方代码注入导入,否则可以安全地删除它。

run yarn add imports-loader运行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/如果您使用 bootstrap3 或其他 CSS 框架,我使用 bootstrap4 数据表,请按照此链接进行安装: https : //datatables.net/download/

in my config/webpack/loaders/datatable.js在我的config/webpack/loaders/datatable.js

module.exports = {
  test: /datatables\.net.*/,
  use: [{
    loader: 'imports-loader?define=>false'
  }]
}

in my config/webpack/environment.js在我的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在我的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您可以随意在app/javascript/packs中的任何.js文件中import './datatable'

None of the above worked for me.以上都不适合我。 Finally got it to work by following this guide: https://inopinatus.org/2019/09/14/webpacker-jquery-and-jquery-plugins/ .最终按照本指南让它工作: https : //inopinatus.org/2019/09/14/webpacker-jquery-and-jquery-plugins/

yarn add datatables.net-bs4 imports-loader

application.js应用程序.js

require('@rails/ujs').start()
require('@rails/activestorage').start()
require('channels')
require('jquery')
require('bootstrap/dist/js/bootstrap')
window.$ = $

require('imports-loader?define=>false!datatables.net')(window, $)
require('imports-loader?define=>false!datatables.net-bs4')(window, $)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM