How to initialize, with colvis from a stimulus controller

How to initialize, with colvis from a stimulus controller

tacman1123tacman1123 Posts: 198Questions: 46Answers: 1
edited December 2022 in Free community support

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

  • allanallan Posts: 63,489Questions: 1Answers: 10,470 Site admin

    Hi,

    let dt = new DataTables(el, setup);
    

    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

  • tacman1123tacman1123 Posts: 198Questions: 46Answers: 1
    edited January 2023

    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:

    import { Controller } from '@hotwired/stimulus';
    
    require("datatables.net-bs5");
    require('datatables.net-select-bs5');
    require('datatables.net-responsive-bs5');
    require('datatables.net-buttons-bs5');
    require('datatables.net-scroller-bs5');
    require('datatables.net-buttons/js/buttons.colVis.min');
    
            let dt = $(el).DataTable(setup);
    
    
    import { Controller } from '@hotwired/stimulus';
    import DataTables from "datatables.net-bs5";
    import('datatables.net-select-bs5');
    import('datatables.net-responsive-bs5');
    import('datatables.net-buttons-bs5');
    import('datatables.net-scroller-bs5');
    import('datatables.net-buttons/js/buttons.colVis.min');
    
            let dt2 = new DataTables(el, setup);
    

    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.

  • tacman1123tacman1123 Posts: 198Questions: 46Answers: 1

    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.

  • allanallan Posts: 63,489Questions: 1Answers: 10,470 Site admin

    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

  • tacman1123tacman1123 Posts: 198Questions: 46Answers: 1

    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!

  • allanallan Posts: 63,489Questions: 1Answers: 10,470 Site admin

    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). Use class="table table-striped responsive" instead.

    3) The datatable_controller.js had scroller enabled but scrollY disabled. That isn't valid. For Scroller to be enabled, we need scrollY. I'm surprised it didn't throw an error about that, but that might be due to issue 1.

    4) The imports should be:

    import { Controller } from '@hotwired/stimulus';
    import DataTables from "datatables.net-bs5";
    import 'datatables.net-select-bs5';
    import 'datatables.net-responsive-bs5';
    import 'datatables.net-buttons-bs5';
    import 'datatables.net-scroller-bs5';
    import 'datatables.net-buttons/js/buttons.colVis.min';
    

    I've done that in both of the two controllers and it loads fine.

    Allan

  • tacman1123tacman1123 Posts: 198Questions: 46Answers: 1

    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:

    <table class="table table-striped responsive" data-survos--api-grid-bundle--api-grid-target="table">
    </table>
    

    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.

    responsive.bootstrap5.mjs:11 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'display')
        at ./node_modules/@survos/api-grid-bundle/node_modules/datatables.net-responsive-bs5/js/responsive.bootstrap5.mjs (responsive.bootstrap5.mjs:11:16)
        at __webpack_require__ (bootstrap:19:1)
        at ./node_modules/@survos/api-grid-bundle/src/controllers/api_grid_controller.js (twig.min.js:3:1)
        at Function.__webpack_require__ (bootstrap:19:1)
    ./node_modules/@survos/api-grid-bundle/node_modules/datatables.net-responsive-bs5/js/responsive.bootstrap5.mjs @ responsive.bootstrap5.mjs:11
    __webpack_require__ @ bootstrap:19
    ./node_modules/@survos/api-grid-bundle/src/controllers/api_grid_controller.js @ twig.min.js:3
    
    
  • allanallan Posts: 63,489Questions: 1Answers: 10,470 Site admin

    What is 'display' in that context?

    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:

    import 'datatables.net-responsive';
    

    as well as the datatables.net-responsive-bs5 import. Add the new one just before the other.

    Allan

  • tacman1123tacman1123 Posts: 198Questions: 46Answers: 1

    That didn't work with the -bs5, but it compiles without it,

    import {default as axios} from "axios";
    import DataTables from "datatables.net-bs5";
    import 'datatables.net-select-bs5';
    import 'datatables.net-responsive';
    // import 'datatables.net-responsive-bs5';
    import 'datatables.net-buttons-bs5';
    import 'datatables.net-scroller-bs5';
    import 'datatables.net-buttons/js/buttons.colVis.min';
    import 'datatables.net-buttons/js/buttons.html5.min';
    import 'datatables.net-buttons/js/buttons.print.min';
    
    
  • tacman1123tacman1123 Posts: 198Questions: 46Answers: 1

    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

    columns: [
                { title: 'Name', data: ..., render: ... },
    

    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:

    buttons: [
                    {
                        extend: 'colvis',
                        columns: 'th:nth-child(n+1)'
                    }
    ]
    

    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.

  • allanallan Posts: 63,489Questions: 1Answers: 10,470 Site admin
    Answer ✓

    If I use:

    import { Controller } from '@hotwired/stimulus';
    import DataTables from "datatables.net-bs5";
    import 'datatables.net-select-bs5';
    import 'datatables.net-responsive';
    import 'datatables.net-responsive-bs5';
    import 'datatables.net-buttons-bs5';
    import 'datatables.net-scroller-bs5';
    import 'datatables.net-buttons/js/buttons.colVis.min';
    

    Then it correctly enables Responsive on the table (due to the use of the responsive class - the same thing could be done with the responsive: true option in the initialisation object:

    Allan

  • paskuale75paskuale75 Posts: 5Questions: 0Answers: 0

    Hi @tacman1123 any info about your api_grid component ? Is still alive ? Thanks

Sign In or Register to comment.