omines / datatables-bundle

DataTables bundle for Symfony
https://omines.github.io/datatables-bundle/
MIT License
251 stars 113 forks source link

jQuery not found when used with AssetMapper #322

Closed auroraeosrose closed 2 months ago

auroraeosrose commented 6 months ago

We're using symfony 7.0 and the new AssetMapper for javascript

import './vendor/datatables.net-bs5/css/dataTables.bootstrap5.min.css';

import jszip from 'jszip';
import pdfmake from 'pdfmake';

import $ from 'jquery';
window.$ = window.jQuery = $;

import 'datatables.net-bs5';
import '@omines/datatables-bundle';

$(document).ready(function() {
    var table = $(tableSelector).initDataTables(datatableSettings, {
        searching: true,
        dom: '<"html5buttons"B>lTfgitp',
        buttons: true,
        scrollX: true,
    }).then(function(dt) {
        // dt contains the initialized instance of DataTables

        dt.on('draw', function() {

        });

    });

});

Using the js file above with assetmapper as an entrypoint you will get the error "jQuery not defined" in the javascript console

You can "cheat" it by doing jquery as a regular js file include in the header of your html file but that negates the whole point of using assetmapper

The fix is to add the following statement into the first line of the datatables.js file included with the bundle

import jQuery from 'jquery';

Now because this is from a bundle we'll have to override the asset for now in our system with a copied file with that statement added but this is suboptimal - upgrading this package means a manual fix for that every single time

Could you ship 2 versions of the bundled javascript file - one with the import statement for symfony assetmapper users and one without for other users?

curry684 commented 6 months ago

Isn't it just much easier to bundle DataTables.js with a jQuery-included-build in that case? They bundle jQuery with the extended builds since nobody uses it elsewhere anymore. You could just link it from a CDN on the table-containing pages:

https://datatables.net/download/ <-- select to include jQuery

Or link https://cdn.datatables.net/1.13.7/js/jquery.dataTables.min.js in a script tag.

Also see: https://datatables.net/manual/installation#Non-jQuery-initialisation

If you have a better solution I'm open to it, but as said - nobody else uses jQuery anymore so are we solving a real problem here?

auroraeosrose commented 6 months ago

I think you're misunderstanding "not having jquery" is not the problem or "not having it bundled" is also not the problem

This is a Loading issue with ES6 style javascript

Using the javascript file provided in an ES6 environment with imports is the issue

The issue is the import statement that is required is missing in your bundled javascript at the moment

please see https://symfony.com/doc/current/frontend/asset_mapper.html#global-variables-like-jquery

curry684 commented 6 months ago

Oops yes we are the problem ourselves, I see. Didn't use AssetMapper myself yet hehe.

I don't really like maintaining 2 almost identical JS files, that's bound to go wrong. I think we should be able to detect $ is missing and then import it automatically?

auroraeosrose commented 6 months ago

I don't know if you can or not - import has to be top level and it can only be in module files https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

Maybe import() would work instead? Would take some trial and error probably :( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import

Would probably take some trial and error. I'm slowly moving a project over that was all nasty jquery to ES6 only ... just wish there was good datatables.net replacement in pretty new JS (I am not that crazy to write it)

I almost think it would be easier to just script the ES6 version of the js file for the project and use github actions (or bash, cause I'm lazy) but since you literally are putting one line at the top then you don't have to maintain 2 identical files - one is just generated on release from the other... but I like automation

curry684 commented 6 months ago

Is your project in a state where you can easily try if something stupid like if (undefined === $) { import jQuery from 'jQuery'; } would work? I would have to set up a specific test case to do the trial and error that is indeed required.

If simple portable solutions like that are not workable we can indeed look into scripting a solution.

auroraeosrose commented 6 months ago
  1. (undefined === $) won't work you have to do ('undefined' === typeof $)
  2. You can't use import statically anywhere but the top of a file. You'd have to use import() instead. (as I thought in the docs)
  3. But import() wants a js file to load ... which assetmapper is dynamically naming and generating

So I don't think it'll work to try to do a dynamic import (which is super annoying) unless someone with more javascript foo has an answer on how to make import() work without a js filename/path

github-actions[bot] commented 4 months ago

Stale issue message

robiinho commented 4 months ago

Hi, about my self this init works with AssetMapper:

        document.addEventListener('DOMContentLoaded', () => {
            $(function () {
                    $('#presidents').initDataTables({{ datatable_settings(datatable) }}, {

import 'datatables.net-bs5/css/dataTables.bootstrap5.min.css'; import 'datatables.net-editor-bs5/css/editor.bootstrap5.min.css';

import '../vendor/omines/datatables-bundle/src/Resources/public/js/datatables.js';


I created a file for fonts with the script.sh from datatables and modify vfs_fonts.js to look like to make it work:  

export default { "Roboto-Italic.ttf":"AAEAAAA

github-actions[bot] commented 2 months ago

Stale issue message