I work with two fantastic JavaScript libraries for my two largest work projects:
I ran into a perplexing problem the other day that took me a few hours to solve. If you are reading this, I imagine you ran into the same problem, and I hope this will help you solve it in quicker time.
I experienced the following symptoms:
This problem happens when:
I don't know what happens exactly, but it seems due to Vue's reactive nature that it hijacks the root HTML element's and descendants' events which it is assigned to, and that renders the DataTable inert.
There are two ways to solve this problem:
Configure your DataTable during the "mounted" event of your Vue object.
Move your DataTable HTML element outside of the root HTML element Vue is bound to.
Below you will see two DataTables that are powered by the same data. The broken one is configured/initialized before the Vue object, and the working one is configured/initialized after the Vue object.
You will see the symptoms I experienced in the broken DataTable and see how it is supposed to work with the Working example.
As you change the Game Category option you will see the Working DataTable update, but not the Broken DataTable.
DataTables is dependent on jQuery, so I will use jQuery's "ready" function for the page's initialization code.
<script>
$(document).ready(function(){
// Creating/Initializing the DataTable before the Vue object leaves it in a broken state after Vue is created/initialized.
const brokenDataTable = $('#broken-datatable').DataTable({
data: trackmaniaData,
columns: [
{ data: 'title', title: 'Title' },
{ data: 'platform', title: 'Platform' }
]
});
const vm = new Vue({
el: '#page',
data: {
gameCategory: 'trackmania',
gameCategories: ['trackmania', 'other'],
gamesData: trackmaniaData,
brokenDataTable: brokenDataTable,
},
methods: {
updateGamesData() {
console.log('updateGamesData with category: ', this.gameCategory);
switch (this.gameCategory) {
case 'trackmania':
this.gamesData = trackmaniaData;
break;
case 'other':
this.gamesData = otherGamesData;
break;
default:
console.log('option not recognized');
break;
}
}
},
watch: {
gameCategory(newGameCategory) {
this.updateGamesData();
},
gamesData(newGamesData) {
this.brokenDataTable.clear().rows.add(newGamesData).draw();
}
}
});
});
</script>