Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DataTables API undefined with Symfony Webpack Encore

I'm using Webpack Encore with Symfony 3.4 (part of migration to Symfony 4).

I have Datatables (installed via NPM to node_modules) working with jQuery but the api functions such as .columns are returning: .column is not a function at

Package Versions:

  • jQuery 2.14.4
  • Datatables 1.10.19
  • Webpack Encore 0.27.0

Webpack app.js:

global.$ = global.jQuery = require('jquery');
require('bootstrap');
global.moment = require('moment');
require('datatables.net-dt');
$.fn.dataTable = $.fn.DataTable = global.DataTable = require('datatables.net');

webpack.config.js:

var Encore = require('@symfony/webpack-encore');

Encore
// directory where compiled assets will be stored
    .setOutputPath('code/web/build/')
    // public path used by the web server to access the output path
    .setPublicPath('/build')
    // only needed for CDN's or sub-directory deploy
    //.setManifestKeyPrefix('build/')

    .addEntry('site', './assets/js/site/app.js')

    // will require an extra script tag for runtime.js
    // but, you probably want this, unless you're building a single-page app
    .enableSingleRuntimeChunk()

    .cleanupOutputBeforeBuild()
    .enableSourceMaps(!Encore.isProduction())
    // enables hashed filenames (e.g. app.abc123.css)
    .enableVersioning(Encore.isProduction())

// uncomment if you use TypeScript
//.enableTypeScriptLoader()

// uncomment if you use Sass/SCSS files
//.enableSassLoader()

// uncomment if you're having problems with a jQuery plugin
//.autoProvidejQuery()
;

module.exports = Encore.getWebpackConfig();

Javascript example in template.html.twig (extends base html file):

{{ encore_entry_script_tags('site') }}

<script type="text/javascript">
$(document).ready(function() {
    var $dtable;

    $dtable = $('#simpleTable')
                        .DataTable({
                            data: data,
                            deferRender: true,
                            scrollX: false,
                            searching: true,
                            paging: true,
                            pageLength: 25});

    console.log($dtable);

    // Error occurs here
    var column = $dtable.column(index);
});
</script>

A console log of $dtable immediately after instantiation outputs the following which seems to confirm an Api instance isn't created?

dtable instance

Is it possible this is related to the DataTable loader that uses the AMD method due to Webpack?

jquery.dataTables.js:

(function( factory ) {
    "use strict";
    if ( typeof define === 'function' && define.amd ) {
        define( ['jquery'], function ( $ ) {
            return factory( $, window, document );
        } );
    }
    else if ( typeof exports === 'object' ) {
        module.exports = function (root, $) {
            if ( ! root ) {
                // CommonJS environments without a window global must pass a
                // root. This will give an error otherwise
                root = window;
            }
            if ( ! $ ) {
                $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
                    require('jquery') :
                    require('jquery')( root );
            }
            return factory( $, root, root.document );
        };
    }
    else {
        factory( jQuery, window, document );
    }
}
like image 259
Dan Avatar asked Apr 15 '19 10:04

Dan


1 Answers

The AMD loader may be a problem here,

Can you try to disable AMD Loader it to see if it work :

var config = Encore.getWebpackConfig();

config.module.rules.unshift({
  parser: {
    amd: false,
  }
});

module.exports = config;

Otherwise you could try to make it work with AMD Loader : First install DataTables :

npm install datatables.net

Then DataTables style (bootstrap) :

npm install datatables.net-bs

Then the imports-loader plugin

Modify your webpack.config.js to make an exception for datatables:

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

Now you should be able to use DataTables :

import 'datatables.net';
import dt from 'datatables.net-bs';
dt(window, $);


//And now use it
$('#exampleDatatable').DataTable();
like image 158
Dylan Kas Avatar answered Sep 30 '22 14:09

Dylan Kas