How to initialize, with colvis from a stimulus controller
How to initialize, with colvis from a stimulus controller
I want to initialize a datatable from a stimulus controller, but I cannot figure out why colvis won't work. I'm using yarn as the package manager, and webpack, and composer for the PHP.
git clone git@github.com:tacman/datatables-colvis-demo.git && cd datatables-colvis-demo
composer install && yarn install && yarn dev
php -S 127.0.0.1:8000 -t public
Trivial example, taken from https://datatables.net/extensions/responsive/examples/column-control/column-visibility.html
The javascript controller works, except for colvis:
import DataTables from "datatables.net-bs5";
import('datatables.net-buttons-bs5');
import('datatables.net-buttons/js/buttons.colVis.min');
export default class extends Controller {
static targets = ['table']
connect() {
super.connect();
let el = this.tableTarget;
let setup = {
dom: 'Bfrtip',
buttons: [
'colvis',
'copy'
]
}
let dt = $(el).DataTable(setup); // still can't figure out how to call this without $()
}
package.json includes this libraries
"datatables.net-bs5": "^1.13.1",
"datatables.net-buttons-bs5": "^2.3.3",
"jszip": "^3.10.1",
"pdfmake": "^0.2.7"
app.scss
@import "datatables.net-bs5";
@import "datatables.net-buttons-bs5";
I know the preferred method is to use a bundler and cdn, but this is part of a Symfony bundle and I want it to be self-contained, that it's installed and everything works out of the box. (and it mostly does, but colviz is problematic).
So I'm obviously missing something, but I've spent hours hacking at it and I'm stuck as to what it is.
Thanks.
This question has an accepted answers - jump to answer
Answers
Hi,
will work for the non-jQuery initialisation of the DataTable with that setup. I haven't yet looked at the ColVis aspect - will do so shortly.
Allan
OK, I think I've finally narrowed down the problem, so the title of this thread can now change to something that more accurately reflects the issue.
In short, require works, but import doesn't.
None of the extensions load when I use import, but they work fine with require.
The only difference is require/include, and the initialization call:
I've updated the github repo mentioned earlier in this thread to include a second stimulus controller, dt_require_controller, which of course uses require and works as expected.
I feel like I'm playing whack-a-mole. There are several ways to configure this, import, require, and autoimport (which comes from Symfony's ux components). There's webpack's .autoProvideJQuery(), or importing/requiring $ from within my stimulus component (a javascript library).
I cannot figure out what magical combination I need for everything to simple load and work. Gut feeling is that while the library is smart enough to figure out how to load itself and various plugins, there's some subtle difference that's triggering different loads, maybe depending on webpack.
Allan, is this something that you can solve for me if I pay for support? I realize Symfony UX and Stimulus are outside of the core datatables project, but certainly both are recognized tools in the web development community. Thanks.
I'm going to get to work on this immediately after lunch. Configuration of Javascript builders and tooling is easily the hardest part of DataTables support at the moment. There are so many millions of tools and each one seems to do things differently! I'll get your repo working shortly
Allan
Thanks, Allan. In fact, it's actually slightly more complicated -- my "real" repo is a Symfony UX component. When it's working, it's really quite cool, and Symfony developers can integrate datatables without writing any javascript.
I'll post a demo, but obviously the first step is the simpler one of supporting both require and import. Thanks for looking at it!
There were a bunch of issues that I've been able to identify while looking at this:
1) Both tables had an id of
example
- that is invalid HTML and can cause issues. You don't need and id for how these tables are used, so I just removed them.2) The table styling is off as you are loading the Bootstrap 5 integration for DataTables, but using a DataTables base styling class (
display
). Useclass="table table-striped responsive"
instead.3) The
datatable_controller.js
hadscroller
enabled butscrollY
disabled. That isn't valid. For Scroller to be enabled, we needscrollY
. I'm surprised it didn't throw an error about that, but that might be due to issue 1.4) The imports should be:
I've done that in both of the two controllers and it loads fine.
Allan
Thanks, Allan! This has helped a lot.
Is there something different about the responsive plugin? Unlike the others, I often get errors using it in my component, but it's only this plugin. The error, though, mentions 'display', as you mentioned in your comment. But I can't anywhere in my code that 'display' is used (after I've changed it to table table-responsive, as you suggested.
responsive.bootstrap5.mjs:11 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'display')
The HTML in this case is simply:
What is 'display' in that context? The datatable's initialization is much more complicated in this case, because it uses ajax and user-defined columns:
https://github.com/survos/SurvosApiGridBundle/blob/main/assets/src/controllers/api_grid_controller.js#L290
So the error can certainly be in that mess somewhere. Can you point me on where to look?
Thanks.
It's just a display control class - see here. If you are using Bootstrap you don't want or need the
display
class.With the error you are seeing now - I think that is a completely different
display
... Try adding:as well as the
datatables.net-responsive-bs5
import. Add the new one just before the other.Allan
That didn't work with the -bs5, but it compiles without it,
Possibly related:
In my api_grid component, I do not create the thead and tr/th elements in HTML. Instead, I dynamically create the column headers using the title property
I mention this, because perhaps responsive can't calculate the table width at that point. I found that colviz didn't work with the default settings, the column names array was empty unless I initialized it with a specific selection:
However, I'm just stabbing here, trying to figure out why it works with an HTML table and not with my ajax-powered table. I could be completely wrong on this.
If I use:
Then it correctly enables Responsive on the table (due to the use of the
responsive
class - the same thing could be done with theresponsive: true
option in the initialisation object:Allan
Hi @tacman1123 any info about your api_grid component ? Is still alive ? Thanks