Modify Ajax URL in DataTables (Vue/Laravel/Options API)

Customizing DataTables in Vue/Laravel

A request came in that’s not completely out of the norm, but something that stumped me for a few hours. It wasn’t anything revolutionary. It was something that I’ve done before with a different type of implementation, but never like this.

The request was, “can we add a dropdown list so that when we select an option, it would only load those items into the DataTables table. We want all of the items to load first and then if we need to narrow it down further, we’d like to have that capability.”

Implementing this using Vue/jQuery is extremely straightforward. Implementing it with Options API proved to be not so much.

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

Following the docs outlined, we were able to install DataTables into our Laravel/Vue application. I’ve written an entire article on this if you’d like to read it.

https://blog.devgenius.io/setting-up-laravel-9-x-with-vue-js-and-datatables-the-vue-approach-fb52dfc74f36

What the code looks like now

Before I started adding any modifications, this is what the current state of the code looks like.

<template>
    <div class="p-6">
        <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},
            ]
        }
    }
}
</script>

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

It loads data from the api, which just returns users from the database table and an edit link.

What We Need

After reading that blog-post, I realized that I needed to use either ajax.reload() or something similar. I found that you can use ajax.url('api/route').load() to change the data content.

The docs state:

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

They had an example that removed a row from the DataTable. Similar concept to what I needed. I can see that they use dt.remove. I just need to use dt.ajax.url('api/route').load().

function remove() {
  dt.rows({ selected: true }).every(function () {
    let idx = data.value.indexOf(this.data());
    data.value.splice(idx, 1);
  });
}

The biggest problem in this whole thing was that it was written with the composition API and not the Options API. It took some time on StackOverflow and even DataTables’ forum to piece together an answer. The answer that I’ll share with you.

The simple test would be a button called Change It that changes the ajax endpoint when pressed and reloads the data into DataTables.

The Solution

The modifications that needed to occur were:

  • Replace ref() with this.$refs
  • Instead of an onMounted(), use mounted() method
  • Within mounted method, use this.dt = this.$refs.table.dt(). I added the dt variable into data(), which is why I needed to use this.dt.
  • Create a method called changeIt that can cause the url change, this.dt.ajax.url(‘api/users/user’).load().
  • Create a button.

The code:

<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>

Just thought that I would share this since the answer is not clear anywhere online.

 

Leave a Reply