Dan
Dan

Reputation: 12096

DataTables not found in Angular Datatables using Webpack Encore

I've been upgrading a Symfony application from 3.4 to 4.2.2, everything is fine but I cannot get DataTables to function via yarn install and webpack encore with angular-datatables.

How I've set it up

Yarn install:

yarn add [email protected]
yarn add [email protected]
yarn add [email protected]
yarn add [email protected]
yarn add [email protected]

Added those files to my Webpack app.js along with jQuery:

var $ = require('jquery');
require('datatables.net');
require('datatables.net-dt');
require('angular');
require('angular-datatables');

Included the app.js inside of my Webpack config file:

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

Encore
    .setOutputPath('public/build/')
    .setPublicPath('/build')

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

    .enableSingleRuntimeChunk()
    .cleanupOutputBeforeBuild()
    .enableBuildNotifications()
    .enableSourceMaps(!Encore.isProduction())
    .enableVersioning(Encore.isProduction())
    .autoProvidejQuery()
;

module.exports = Encore.getWebpackConfig();

and included the above in my front-end template via:

{{ encore_entry_script_tags('app') }}

The Error

The above results in the following Javascript error which seems to show the DataTables API is not accessible.

Uncaught TypeError: Cannot read property 'Api' of undefined
at initAngularDataTables (angular-datatables.js:478)
at Object.invoke (angular.js:4523)


/* @ngInject */
function initAngularDataTables() {
    if ($.fn.DataTable.Api) {
        /**
         * Register an API to destroy a DataTable without detaching the tbody so that we can add new data
         * when rendering with the "Angular way".
         */
        $.fn.DataTable.Api.register('ngDestroy()', function(remove) {
            remove = remove || false;




Possible Solution

I've tried the following hacky fix but it means I have to have my Angular code in the same app.js file else it doesn't work. It also means some functions still fail...

global.$ = global.jQuery = require('jquery');

require('jquery-ui');
require('bootstrap');
require('admin-lte');
require('datatables.net-dt');
global.moment = require('moment');

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

Error:

TypeError: _oTable.ngDestroy is not a function
    at _destroyAndCompile (angular-datatables.js:947)

Upvotes: 5

Views: 1084

Answers (1)

Munim Munna
Munim Munna

Reputation: 17556

Your project has datatables.net and datatables.net-dt as dependency, and both of them has their own dependency (jQuery>1.7). If you don't specify a jQuery version for your project, your dependency tree end up with the latest version of jQuery which is also used by your dependencies.

├─[email protected]
├─[email protected]
└─[email protected]

But if you specify an old version of jQuery, your dependency tree end up fetching the latest version of jQuery for your dependencies (yarn does it, npm does not, I don't know why).

├─[email protected]
├─[email protected]
│      └─[email protected]
└─[email protected]
       └─[email protected]

As a result, you have 2 different jQuery in your porject.

const jQuery = require('jquery')
console.log(jQuery.fn.jquery) // logs 2.1.4
const DataTable = require('datatables.net')
console.log(DataTable.$.fn.jquery) // logs 3.3.1

As DataTable binds itself to an encapsulated instance of jQuery, jQuery.fn.dataTable is obviously undefined. To fix this issue, just use the latest version of jQuery in your project. Or you can recommend yarn to use a fixed version of jQuery for all of it's dependencies adding a resolution directive to your package.json file.

"dependencies": {
    "angular": "1.4.8",
    "angular-datatables": "0.6.2",
    "datatables.net": "1.10.19",
    "datatables.net-dt": "^1.10.19",
    "jquery": "2.1.4"
},
"resolutions": {
    "jquery": "2.1.4"
}

Then execute yarn install command, and your unwanted jQuery installations will be taken care of.

Upvotes: 2

Related Questions