0

ajax.reload() and/or ajax.url().load() is just not working for Vue3 DataTable integration. It works if you include the CDN and follow the jQuery approach to it.

If you follow the instructions on the DataTables website on how to integrate DataTables into Vue3, that feature just doesn't seem to work.

https://datatables.net/blog/2022-06-22-vue

For example:

<template>
    <div class="p-6">
        <button @click="changeIt">
            Change
        </button>

        <DataTable
            class="display"
            id="datatable"
            :columns="columns"
            :ajax="{
                url: 'api/users',
            }"
            ref="table"
            :options="{
                select: true,
                serverSide: true,
            }"
        >
            <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Email</th>
                <th>Action</th>
            </tr>
            </thead>
            <tbody>
            </tbody>
        </DataTable>
    </div>
</template>

<script>
import DataTable from 'datatables.net-vue3'
import DataTablesLib from 'datatables.net';

DataTable.use(DataTablesLib);

export default {
    name: 'DataTableComponent',
    components: {DataTable},
    data(){
        return {
            columns: [
                {"data": "id"},
                {"data": "name"},
                {"data": "email"},
                {"data": "action", "sortable": false},
            ],
        }
    },
    methods: {
        changeIt() {
            $('#datatable').DataTable().ajax.url('users/user').load();
        }
    },
}
</script>

<style>
@import 'datatables.net-dt';
</style>

For a simple example, if you click the button, there would be a new Ajax request to somewhere else. This does not currently work.

The error that I get is:

runtime-core.esm-bundler.js:218 Uncaught TypeError: $(...).DataTable is not a function
    at Proxy.changeIt (DataTableComponent.vue:55:29)
    at _createElementVNode.onClick._cache.<computed>._cache.<computed> (DataTableComponent.vue:3:25)
    at callWithErrorHandling (runtime-core.esm-bundler.js:155:22)
    at callWithAsyncErrorHandling (runtime-core.esm-bundler.js:164:21)
    at HTMLButtonElement.invoker (runtime-dom.esm-bundler.js:369:13)

I've tried every combination, and it doesn't seem to work. For example:

$('#datatable').DataTable().ajax.url('users/user').load();
$('#datatable').DataTable.ajax.url('users/user').load();
$('#datatable').ajax.url('users/user').load();
DataTable().ajax.url('users/user').load();
DataTable.ajax.url('users/user').load();

Any ideas?

EDIT I did find that DataTables provides a dt() function, but it's still not working. It recommends the following:

DataTables API Update and delete are very similar in that we just manipulate the array of data, but we will need to access the DataTables API to know which rows have been selected by the end user. The DataTable component provides a dt() method that we can use to get this via a Vue reference:

let dt;
const table = ref(); // This variable is used in the `ref` attribute for the component
 
onMounted(function () {
  dt = table.value.dt();
});

So the modified code looks like this, but still doesn't work.

<template>
    <div>
        <h1>Simple table</h1>
        <button @click="changeIt">Change It</button>

        <DataTable
            class="display"
            id="datatable"
            :columns="columns"
            ajax="api/users"
            ref="table"
            :options="{
                select: true,
                serverSide: true,
            }"
        >
            <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Email</th>
                <th>Action</th>
            </tr>
            </thead>
            <tbody>
            </tbody>
        </DataTable>
    </div>
</template>

<script>
import DataTable from 'datatables.net-vue3';
import DataTablesLib from 'datatables.net';
import 'datatables.net-select';
import {onMounted, ref} from "vue";

DataTable.use(DataTablesLib);

export default {
    name: "DataTableComponent",
    components: {DataTable},
    data(){
        return {
            columns: [
                {"data": "id"},
                {"data": "name"},
                {"data": "email"},
                {"data": "action", "sortable": false},
            ]
        }
    },
    setup() {
        let dt;
        const table = ref();

        onMounted(() => {
            dt = table.value.dt();
        });

        return {
            dt,
        }
    }
}

</script>

<style>
@import 'datatables.net-dt';
</style>

Code Sandbox: https://codesandbox.io/s/serverless-pond-4mu4zw?file=/src/App.vue

EDIT #2: And I got it to work like this, if I use the <script setup> tag. Still can't get it to work in the export default.

https://codesandbox.io/s/festive-forest-1ojspm?file=/src/App.vue:514-719

EDIT #3 (SOLUTION):

Solved with the help of @Aleksandr Savkin. I had to use this.$refs in mounted() and not ref() as the docs suggested.

<template>
    <div>
        <h1>Simple table</h1>
        <button @click="changeIt">Change It</button>

        <DataTable
            class="display"
            id="datatable"
            :columns="columns"
            ajax="api/users"
            ref="table"
            :options="{
                select: true,
                serverSide: true,
            }"
        >
            <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
                <th>Email</th>
                <th>Action</th>
            </tr>
            </thead>
            <tbody>
            </tbody>
        </DataTable>
    </div>
</template>

<script>
import DataTable from 'datatables.net-vue3';
import DataTablesLib from 'datatables.net';
import 'datatables.net-select';

DataTable.use(DataTablesLib);

export default {
    name: "DataTableComponent",
    components: {DataTable},
    data(){
        return {
            columns: [
                {"data": "id"},
                {"data": "name"},
                {"data": "email"},
                {"data": "action", "sortable": false},
            ],
            dt: null,
        }
    },
    mounted() {
        this.dt = this.$refs.table.dt();
    },
    methods: {
        changeIt() {
            this.dt.ajax.url('api/users/user').load();
        }
    }
}

</script>

<style>
@import 'datatables.net-dt';
</style>
Dino Cajic
  • 138
  • 1
  • 7

2 Answers2

1

Maybe it'll help you!

You tried to get a table element using Jquery, but it's not Vue's way to get a component.

I noticed you use the Vue's ref attribute for the DataTable component, so use that to get the component, like this-

methods: {
  changeIt() {
    const componentTable = this.$refs.table;
    componentTable.ajax.url('users/user').load();
  }
},

Also, see this- Template refs documentation

Neha Soni
  • 3,935
  • 2
  • 10
  • 32
  • I was really hoping that this one would work. It seemed like it, but I'm getting the same results unfortunately. – Dino Cajic Dec 17 '22 at 22:23
  • @DinoCajic Can you provide some example on stackblitz/codesandbox? – Aleksandr Savkin Dec 18 '22 at 12:29
  • https://codesandbox.io/s/serverless-pond-4mu4zw?file=/src/App.vue – Dino Cajic Dec 18 '22 at 15:44
  • And I got it to work like this, if I use the – Dino Cajic Dec 18 '22 at 17:14
  • There was just one thing missing from your response and that was the dt() at the end. See my response below with the full code. So, const componentTable = this.$refs.table.dt() should have been in mounted() and then componentTable.ajax.url('api/users/user').load(); should have been in the changeIt – Dino Cajic Dec 18 '22 at 20:22
  • Ok, I fixed it here - https://codesandbox.io/s/youthful-fire-izd9c2?file=/src/App.vue Examples in datatable docs are a little confusing, please take a look at the difference between [Compositions API](https://vuejs.org/guide/introduction.html#composition-api) in Vue (setup method of export default or – Aleksandr Savkin Dec 18 '22 at 20:24
  • That did it. I came to the same conclusion literally 2 minutes ago :). Thanks for your help! – Dino Cajic Dec 18 '22 at 20:27
0

DataTables requires jQuery. Don't select either version if you already have it.

So, verify if you are-

  1. Failing to contain the DataTables library.
  2. Loading the DataTables library before the jQuery library.
  3. Loading the jQuery library double.
  4. Selecting the wrong route to the jQuery files.

For instance, in your HTML file at the head section, verify those-

   <!--  Load CSS file for DataTables  -->
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.21/css/jquery.dataTables.min.css"
      integrity="sha512-1k7mWiTNoyx2XtmI96o+hdjP8nn0f3Z2N4oF/9ZZRgijyV4omsKOXEnqL1gKQNPy2MTSP9rIEWGcH/CInulptA=="
      crossorigin="anonymous"
      referrerpolicy="no-referrer"
    />

    <!--  load jQuery  -->
    <script
      src="https://code.jquery.com/jquery-3.6.0.min.js"
      integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
      crossorigin="anonymous"
    ></script>

    <!--  load DataTables  -->
    <script
      src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.21/js/jquery.dataTables.min.js"
      integrity="sha512-BkpSL20WETFylMrcirBahHfSnY++H2O1W+UnEEO4yNIl+jI2+zowyoGJpbtk6bx97fBXf++WJHSSK2MV4ghPcg=="
      crossorigin="anonymous"
      referrerpolicy="no-referrer"
    ></script>

For more information, refer this documentation- https://bobbyhadz.com/blog/jquery-datatable-is-not-a-function

Neha Soni
  • 3,935
  • 2
  • 10
  • 32
  • If you follow the Vue3@Datatables approach, it doesn't add DataTable function. For example, this works if you load it via jQuery like this. created() { jQuery(document).ready( function ($) { $('#myTable').DataTable({ "processing": true, "serverSide": true, "ajax": "api/wheels", "columns": [ { "data": "id" }, { "data": "name" }, { "data": "email" }, ] }); }); }, – Dino Cajic Dec 17 '22 at 22:25