$(...).DataTable is not a function when using Laravel Mix
Asked Answered
F

5

10

I struggle using Laravel Mix and DataTables. The issue I have is that when I compile down my .js-files etc., each time I would then visit a page that would execute a jQuery datatable, the follwoing error is thrown:

The error is:

jQuery.Deferred exception: $(...).DataTable is not a function TypeError: $(...).DataTable is not a function
Uncaught TypeError: $(...).DataTable is not a function

From what I understand, $(...).DataTable is not a global variable, but how can I make sure that it is accessible "on a global scope" / within my app?

The following is my setup:

app.js

import jquery from 'jquery/dist/jquery.slim'
import 'bootstrap-sass'
import 'datatables.net';
import dt from 'datatables.net-bs';

window.$ = window.jQuery = jquery;

webpack.mix.js

mix
    .js('resources/assets/admin/js/app.js', 'js/')
    .extract([
        'jquery', 'bootstrap-sass', 'datatables.net', 'datatables.net-bs'
    ])
    .autoload({
        jquery: ['$', 'window.jQuery', 'jQuery', 'jquery'],
        DataTable : 'datatables.net-bs'
    })

Any idea would be highly appreciated.

Fathometer answered 21/10, 2017 at 23:39 Comment(5)
Check datatables.net-bs npm page. var $ = require( 'jquery' ); require( 'datatables.net-bs' )( window, $ )Philippic
same goes for datatables.net. From npm page var $ = require( 'jquery' ); require( 'datatables.net' )( window, $ );Philippic
I have tried that before and it caused this issue: Uncaught ReferenceError: $ is not defined. Is there no way to import it?Fathometer
Updated answer, import $ from 'jquery';Philippic
Or, in your case, import $ from 'jquery-slim'. I missed that's slim versionPhilippic
P
10

EDIT: while this answer worked at the time that it was posted and accepted, looks like it's not the case anymore. For anyone looking for the updated solution, other answers are up to date

Yevgeniy Afanasyev

Alexander Gallego L.

Artistan

Because this is accepted answer, I will add the new the solution, but the credit for this should go to people who provided updated answers

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

require( 'datatables.net' );
require( 'datatables.net-bs' );

Original answer

Looking at npmjs pages for datatables.net and the datatables.net-bs

They should be initialized like this

var $ = require( 'jquery' );
require( 'datatables.net' )( window, $ );
require( 'datatables.net-bs' )( window, $ );

Which we could transform into this

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

// in this call we're attaching Datatables as a jQuery plugin
// without this step $().DataTable is undefined
dt( window, $ )
// we need to do the same step for the datatables bootstrap plugin
dt_bs( window, $ )

But if you really want to use import .. from .., take a look into MDN import documentation

import $ from 'jquery/dist/jquery.slim';
import * as dt from 'datatables.net';
import * as dt_bs from 'datatables.net-bs';

dt( window, $ )
dt_bs( window, $ )
Philippic answered 22/10, 2017 at 3:22 Comment(7)
I'm having the error with the first approach saying: Uncaught TypeError: Cannot set property '$' of undefinedHendren
@YevgeniyAfanasyev - i am having the same issue with most recent packages, any solution?Boatyard
I posted my answer to this question.Hendren
This does not work. The module contains a self invoking function, all it returns is the datatable object the module attaches to the $.fn it tries to resolve automatically. So their documentation doesn't match their code. This self invoking function requires jquery itself, however, if I edit the datatables module, and assign the require('jquery') to the window object, the jquery module loaded by DataTables is not the instance of the module loaded by my main app.js. They appear not equal when compared with ===.Kaffraria
@thephpdev, you are right. At the time of posting this answer, my code example worked, but I guess something changed since then. I've updated my answer. I hope other people who provided answer here don't mind that I used their solution as this was accepted answer. I gave them credit for that thoPhilippic
After literal hours of trial and error, the following "worked." window.$ = window.jQuery = require("jquery"); require('datatables.net'); require('datatables.net-dt');Paperweight
@AlexBarker I've updated the answer for the window.$ = window.jQuery = ...Philippic
B
8

For the latest Laravel Mix...

do not invoke the required datatable packages in webpack, leave off the (...)

this will load bootstrap, jquery, datatables, and many of the plugins for datatables without any issues...

window._ = require( 'lodash' );;
window.$ = window.jQuery = require( 'jquery' );;
window.Popper = require('popper.js').default;

// bootstrap
require('bootstrap');

// bootstrap datatables...
require( 'jszip' );
require( 'datatables.net-bs4' );
require( 'datatables.net-buttons-bs4' );
require( 'datatables.net-buttons/js/buttons.colVis.js' );
require( 'datatables.net-buttons/js/buttons.flash.js' );
require( 'datatables.net-buttons/js/buttons.html5.js' );
require( 'datatables.net-buttons/js/buttons.print.js' );
require( 'datatables.net-autofill-bs4' );
require( 'datatables.net-colreorder-bs4' );
require( 'datatables.net-fixedcolumns-bs4' );
require( 'datatables.net-fixedheader-bs4' );
require( 'datatables.net-responsive-bs4' );
require( 'datatables.net-rowreorder-bs4' );
require( 'datatables.net-scroller-bs4' );
require( 'datatables.net-select-bs4' );
// bs4 no js - require direct component
// styling only packages for bs4
require( 'datatables.net-keytable' );
require( 'datatables.net-rowgroup' );
// pdfMake
var pdfMake = require('pdfmake/build/pdfmake.js');
var pdfFonts = require('pdfmake/build/vfs_fonts.js');
pdfMake.vfs = pdfFonts.pdfMake.vfs;

no need for the other code in webpack.mix.js

.extract([
    'jquery', 'bootstrap-sass', 'datatables.net', 'datatables.net-bs'
])
.autoload({
    jquery: ['$', 'window.jQuery', 'jQuery', 'jquery'],
    DataTable : 'datatables.net-bs'
})
Boatyard answered 29/6, 2018 at 18:19 Comment(2)
Man, You save my day. Works Great with Laravel-Mix 4.0.7, Datatables 1.10.19 and Datatables Buttons 1.5.6.Unwilled
You save my day. ThanksCoverdale
H
3

Solution (1)

This is how it worked for me:

require('datatables.net');
require('datatables.net-bs4');

Solution (2)

Below is how it was before and it was causing an error: "$(…).DataTable is not a function":

var a = require('../../../node_modules/datatables.net/js/jquery.dataTables.js');
var b = require('../../../node_modules/datatables.net-bs4/js/dataTables.bootstrap4.js');

this is how I fixed it, but the top solution is obviously recommended

window.$.fn.DataTable = a;
window.$.fn.DataTable = b;

Please comment if you know the reasons behind the magic. Question is "why do direct links to js files work differently comparing to links to packages?"

Hendren answered 24/4, 2018 at 0:17 Comment(0)
G
2

For all functions i load in bootstrap this:

try {
window.Popper = require('popper.js').default;
window.$ = window.jQuery = require('jquery');

require('bootstrap');

window.JSZip = require("jszip");
//require( "pdfmake" );
require( 'datatables.net-bs4' );
require( 'datatables.net-buttons-bs4' );
require( 'datatables.net-buttons/js/buttons.colVis.js' );
require( 'datatables.net-buttons/js/buttons.flash.js' );
require( 'datatables.net-buttons/js/buttons.html5.js' );
require( 'datatables.net-buttons/js/buttons.print.js' );
require( 'datatables.net-colreorder-bs4' );
require( 'datatables.net-fixedcolumns-bs4' );
require( 'datatables.net-responsive-bs4' );
require( 'datatables.net-rowreorder-bs4' );
require( 'datatables.net-scroller-bs4' );
require( 'datatables.net-keytable' );
require( 'datatables.net-rowgroup' );

} catch (e) {}

I work with Laravel 5.7 and npm 6.4.1

Gradeigh answered 20/11, 2018 at 18:59 Comment(0)
S
1

I just want to add to Artistan's answer (I can't comment). I was able to get the CSV, Copy, and PDF buttons to appear using his code, but not the Excel button, until I changed this line

require( 'jszip' );

to this

window.JSZip = require('jszip');

After that, both the generic 'excel' and the 'excelHtml5' buttons appeared.

Sawyers answered 22/7, 2021 at 19:21 Comment(1)
Thank you for this. Just wanted to add that when using import JSZip from "jszip" you can just add window.JSZip = JSZip after your imports to achieve the same resultShuma

© 2022 - 2024 — McMap. All rights reserved.