wenzhixin / bootstrap-table

An extended table to integration with some of the most widely used CSS frameworks. (Supports Bootstrap, Semantic UI, Bulma, Material Design, Foundation, Vue.js)
https://bootstrap-table.com/
MIT License
11.74k stars 4.44k forks source link

$('#table').bootstrapTable is not a function #4763

Closed belashjack closed 4 years ago

belashjack commented 4 years ago

After updating from bootstrap-table v. 1.14.2 to bootstrap-table v. 1.15.2 I got this error

Uncaught TypeError: $('#table').bootstrapTable is not a function

Note:

I found that he problem is that bootstrapTable function doesn't end up in jQuery elements prototype. I looked to the dist folder in node_modules/bootstrap-table/dist/bootstrap-table.js and saw this (for v 1.15.2):

(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('jquery')) :
    typeof define === 'function' && define.amd ? define(['jquery'], factory) :
    (global = global || self, global.BootstrapTable = factory(global.jQuery));
}(this, function ($) {
    // do some stuff
    $.fn.bootstrapTable = function (option, ...args) { ... }
    // do some other stuff
 }));

while for version for v 1.14.2 it looked like this:

(function (global, factory) {
  if (typeof define === "function" && define.amd) { define([], factory); }
  else if (typeof exports !== "undefined") { factory(); }
  else {
    var mod = {
      exports: {}
    };
    factory();
    global.bootstrapTable = mod.exports;
  }
})(this, function () {
    // do some stuff
    $.fn.bootstrapTable = function (option, ...args) { ... }
    // do some other stuff
});

The thing is that in version 1.15.2. we require new instance of jQuery, so when I use $('#table').bootstrapTable, $ here is different form the same variable in bootstrap-table.js, but in 1.14.2 we use global $ variable, so when I use $('#table').bootstrapTable, $ is the same object as in in bootstrap-table.js, so we have our bootstrapTable function.

So the question is why it is different now and how can I resolve my issue?

wenzhixin commented 4 years ago

Which version of jQuery do you use? Can you provide a jsfiddle to show your problem?

belashjack commented 4 years ago

jQuery 3.3.1, I’ll try to provide you with jsfiddle as soon as possible but not now, but as I understand it can be due to some version incompatibility?

wenzhixin commented 4 years ago

https://bootstrap-table.com/docs/getting-started/introduction/#starter-template We are using jQuery 3.3.1, and it works well.

belashjack commented 4 years ago

It’s just strange because upgrade from 1.11.2 to 1.14.2 went smoothly too, all the time jQuery 3.3.1 was used. I noticed that you rewrote the whole app to new ES 2015+ syntax after 1.14.* and I can’t figure out why now new jQuery instance is required in resulting bundle (and causes the error)

wenzhixin commented 4 years ago

It is better to provide online examples to find problems.

belashjack commented 4 years ago

I couldn't recreate it, my product is too big, but in my product it is still an error in a simple case like this https://codepen.io/belashjack/pen/KKwqeNv I thought that the error may be because of my bundle process, but I don't see any changes there, everything is fine. I only update bootstrap-table library and do nothing more and the problem appears. I would be glad if you could give me some hints about factory(require('jquery')) line and how it works underneath, because this didn't come from nowhere, there is some logic to require new jQuery instance

wenzhixin commented 4 years ago

I cannot find an error in your simple case. Are you using import 'bootstrap-table' in your product?

belashjack commented 4 years ago

There is no error in codepen, and there is no error in real product with v. 1.14.2 and below, error appears only in 1.15.*.

No, I require it in shared/vendor.js

// shared/vendor.js
require('bootstrap-table/dist/bootstrap-table.js');

and later import vendor.js in app.react.js which is the main react file where I call ReactDOM.render()

// app.react.js
import 'shared/vendor';
...

jQuery is loaded before react bundle and global $ is accessible in React in both cases, so jQuery should not be the cause of the problem.

wenzhixin commented 4 years ago

I think you need to require jQuery in the same way:

// shared/vendor.js
require('jquery');
require('bootstrap-table/dist/bootstrap-table.js');

After v1.15, we used rollup to build the library, so the output code changed.

belashjack commented 4 years ago

I think I found the problem. I include jquery via <script> tag, not via node_modules. And in my resulting bundle your https://github.com/wenzhixin/bootstrap-table/blob/c7011300838c43303fb64fcd8044e27396cfaeec/dist/bootstrap-table.js#L2 line becomes

factory(__webpack_require__(/*! jquery */ "./node_modules/jquery/dist/jquery.js"))

So it always looks for jquery in node_modules, where I don't have jquery.

But shouldn't your library be agnostic to the way jquery is included? Or at least have jquery in dependency list? Other libs just use jQuery global variable as you did prior to 1.15.*

wenzhixin commented 4 years ago

There is peer dependency: https://github.com/wenzhixin/bootstrap-table/blob/develop/package.json#L57

warning " > bootstrap-table@1.15.5" has unmet peer dependency "jquery@1.9.1 - 3".

So I think you can include bootstrap-table via <script> tag to solve the problem.

belashjack commented 4 years ago

Sorry, didn't notice the warning. Including bootstrap-table via <script> won't solve the problem because it still requires jquery from node_modules. I am pretty sure my problem will be solved if I include my jQuery via npm, it's not easy though.

But I am still wondering why the behavior was changed and you don't just use jQuery global variable. I believe this is the right way. Can you shed a light on it? And I believe it would be helpful to put the info about this breaking changes somewhere in the docs/news/...

Thanks for your time.

LabInc-Nico commented 4 years ago

Hello, I use bootstrap-table (1.15) with webpack (ie webpack-encore symfony) and I had this problem but it works now with the configuration below :

import in my entry point :

file:app.js
import $ from 'jquery';
import 'bootstrap'
import 'bootstrap-table';

I hope it helps Nico

belashjack commented 4 years ago

I am closing the issue because in general I know now what the problem is and there is nothing to add, but still would like to hear why you require jQuery from node_modules instance instead of using global jQuery variable since version 1.15.*

kerog commented 4 years ago

@belashjack Are you used tableexport, or better "tableexport.jquery.plugin": "^1.10.16"? In laravel webpack I have this:

window.$ = window.jQuery = require('jquery');
    require('bootstrap');
    require('bootstrap-table');
    require('bootstrap-table/dist/bootstrap-table-locale-all.min');
    require('tableexport.jquery.plugin');
    require('bootstrap-table/dist/extensions/export/bootstrap-table-export.min');

And this working for me.