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.
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()
withthis.$refs
- Instead of an
onMounted()
, usemounted()
method - Within
mounted
method, usethis.dt = this.$refs.table.dt()
. I added thedt
variable intodata()
, which is why I needed to usethis.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.