Search code examples
phplaravelbootstrap-4datatablesmdbootstrap

Laravel Conflicting Scripts, Bootstrap


With my current Laravel project I am using (attempting) both Bootstrap and MDBoostrap. Currently, I'm getting the error TypeError: $(...).DataTable is not a function and from reading up on this online, this is usually due to jquery being called multiple times. I believe the error has to do with app.js but if I only include the scripts Bootstraps requires for a datatable I get the error that $ is undefined. Note: index.blade.html is extending from app.blade.html. With Laravel, I'm only trying to use MDB to create a datatable. This may be a duplicate from here but this question never got answered. I've been banging my head on this problem for a whole day now, any input is appreciative.

app.blade.html

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="{{asset('css/app.css')}}">

    <title>Laravel Project</title>

</head>
<body>
<div class="container">
    @yield('content')
</div>
<script src="{{asset('js/app.js')}}"></script>
<script>
    // Material Design example
    $(document).ready(function () {
        $('#dtMaterialDesignExample').DataTable();
        $('#dtMaterialDesignExample_wrapper').find('label').each(function () {
            $(this).parent().append($(this).children());
        });
        $('#dtMaterialDesignExample_wrapper .dataTables_filter').find('input').each(function () {
            const $this = $(this);
            $this.attr("placeholder", "Search");
            $this.removeClass('form-control-sm');
        });
        $('#dtMaterialDesignExample_wrapper .dataTables_length').addClass('d-flex flex-row');
        $('#dtMaterialDesignExample_wrapper .dataTables_filter').addClass('md-form');
        $('#dtMaterialDesignExample_wrapper select').removeClass('custom-select custom-select-sm form-control form-control-sm');
        $('#dtMaterialDesignExample_wrapper select').addClass('mdb-select');
        $('#dtMaterialDesignExample_wrapper .mdb-select').materialSelect();
        $('#dtMaterialDesignExample_wrapper .dataTables_filter').find('label').remove();
    });
</script>

</body>
</html>

index.blade.html

@extends('layouts.app')

@section('content')
    <h1>User Table</h1>

    @if(count($users) > 0)
        <table id="dtMaterialDesignExample" class="table" cellspacing="0" width="100%">
            <thead>
            <tr>
                <th class="th-sm">ID
                </th>
                <th class="th-sm">Name
                </th>
                <th class="th-sm">Occupation
                </th>
                <th class="th-sm">Location
                </th>
                <th class="th-sm">Salary
                </th>
            </tr>
            </thead>
            <tbody>
            @foreach($users as $user)
                <tr>
                    <td>{{$user->id}}</td>
                    <td>{{$user->name}}</td>
                    <td>{{$user->occupation}}</td>
                    <td>{{$user->location}}</td>
                    <td>{{$user->salary}}</td>
                </tr>
            @endforeach
            </tbody>
        </table>
    @endif
@endsection

UsersController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\User;

class UsersController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $users = User::orderBy('id', 'asc')->paginate(10);
        return view('users.index',['users'=>$users]);
    }

bootstrap.js

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

    require('bootstrap');
    require('mdbootstrap');
} catch (e) {}

app.js

require('./bootstrap');
var moment = require('mdbootstrap');

app.scss

// Fonts
@import url('https://fonts.googleapis.com/css?family=Nunito');

// Variables
@import 'variables';

// Bootstrap
@import '~bootstrap/scss/bootstrap';

// MDBootstrap
@import '~mdbootstrap/css/mdb.min.css';

Solution

  • If this is the DataTables.net package I believe you have to include JS and possibly the CSS in order to have $('#dtMaterialDesignExample').DataTable(); succeed. I know those do not come with Bootstrap out of the box. I have a Laravel package using vanilla Bootstrap and I had to include the JS and CSS to render data tables.

    I'm not terribly familiar with MDB. They may provide CSS, but I don't know if they provide the JS. It doesn't appear that you should have a duplicate definition so you need to make sure you're app is rendering something like the following to the browser:

    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css"/>
    <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js" type="text/javascript"></script>
    

    That would include the JS definition of the DataTable() function.