Ajax Reload on Vue.js DataTables

Ajax Reload on Vue.js DataTables

dinocajicdinocajic Posts: 4Questions: 1Answers: 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 https://datatables.net/blog/2022-06-22-vue on how to integrate DataTables into Vue3, that feature just doesn't seem to work.

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)

This question has an accepted answers - jump to answer

Answers

  • kthorngrenkthorngren Posts: 21,171Questions: 26Answers: 4,922
    Answer ✓

    I'm not familiar with VUE but this section of the blog you linked to shows how to get an instance of the API which is what $('#datatable').DataTable() would do in a Javascript environment.

    Kevin

  • dinocajicdinocajic Posts: 4Questions: 1Answers: 0

    Thanks Kevin (@kthorngren). I've tried that too...and can't believe I missed that..and I'm still not getting access to it.

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

    Error that I get:
    TypeError: Cannot read properties of undefined (reading 'dt')

  • dinocajicdinocajic Posts: 4Questions: 1Answers: 0

    OK, So I got it to work, but I'm missing something here. The onMounted function is the culprit. It works if I use the <script setup> tag.

    <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 setup>
    import {onMounted, ref} from "vue";
    
    let dt;
    const table = ref();
    
    onMounted(() => {
        dt = table.value.dt();
    });
    
    function changeIt() {
        dt.ajax.url('api/users/user').load();
    }
    </script>
    
    <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},
                ]
            }
        },
    }
    
    </script>
    
    <style>
    @import 'datatables.net-dt';
    </style>
    
  • dinocajicdinocajic Posts: 4Questions: 1Answers: 0

    Solved. Needed 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>
    
Sign In or Register to comment.