javascript - DataTables API undefined with Symfony Webpack Encore - Stack Overflow

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

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-dt');
$.fn.dataTable = $.fn.DataTable = global.DataTable = require('datatables');

webpack.config.js:

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

Encore
// directory where piled 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())

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

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

// unment 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?

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 );
    }
}

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-dt');
$.fn.dataTable = $.fn.DataTable = global.DataTable = require('datatables');

webpack.config.js:

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

Encore
// directory where piled 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())

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

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

// unment 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?

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 );
    }
}
Share Improve this question asked Apr 15, 2019 at 10:15 DanDan 12.1k14 gold badges55 silver badges117 bronze badges 0
Add a ment  | 

4 Answers 4

Reset to default 5 +100

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

Then DataTables style (bootstrap) :

npm install datatables-bs

Then the imports-loader plugin

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

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

Now you should be able to use DataTables :

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


//And now use it
$('#exampleDatatable').DataTable();

The issue I see is with line:

$.fn.dataTable = $.fn.DataTable = global.DataTable = require('datatables');

dataTable() and DataTable() are not equivalent.

The correct functions will be added to Jquery by the factory, no need to set these. Actually, if I can guess, the above code will overwrite DataTable() with dataTable().

Change to:

require('datatables');

It should work.

Maybe it's a stupid idea ... but what is the data value in your template-defined call $('#simpleTable').DataTable({data:data, ...}) call?

According to docs (3rd paragraph) setting the data option (even with an empty value) will override the data from the table. If your value data is undefined, this might turn your data-rich table into a vegetable in the eyes of DataTable.

I assume that your table is fine, the module is loaded fine, ... so the data might be the problem ...

If, however, it does contain useful data, would you mind posting some example of it? ;o)

The DataTables documentation for using with NPM show that the export is a function that returns the DataTable API.

var dt = require( 'datatables' )(); // N.b. the extra parenthesis.

So it's likely you'd need to alter your global assignment; something like this might work:

$.fn.dataTable = $.fn.DataTable = global.DataTable = require('datatables')(); // N.b. the extra parentheses.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745064729a4609186.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信