Reputation: 7017
I have a Datatables.net jquery plugin as a vue component:
DatatablesCGU:
<template>
<table v-bind="$props" ref="tableElement" class="table table-striped table-hover table-bordered">
<slot></slot>
</table>
</template>
<script>
import $ from 'jquery';
// Datatables
require('datatables.net-bs');
require('datatables.net-bs4/js/dataTables.bootstrap4.js');
require('datatables.net-buttons');
require('datatables.net-buttons-bs');
require('datatables.net-responsive');
require('datatables.net-responsive-bs');
require('datatables.net-responsive-bs/css/responsive.bootstrap.css');
require('datatables.net-buttons/js/buttons.colVis.js'); // Column visibility
require('datatables.net-buttons/js/buttons.html5.js'); // HTML 5 file export
require('datatables.net-buttons/js/buttons.flash.js'); // Flash file export
require('datatables.net-buttons/js/buttons.print.js'); // Print view button
require('datatables.net-keytable');
require('datatables.net-keytable-bs/css/keyTable.bootstrap.css');
require('datatables.net-select');
require('jszip/dist/jszip.js');
require('pdfmake/build/pdfmake.js');
require('pdfmake/build/vfs_fonts.js');
//Evita o alert chato do datatables em caso de erro
$.fn.dataTable.ext.errMode = function ( settings, helpPage, message ) {
console.error(message);
};
/**
* Wrapper component for dataTable plugin
* Only DOM child elements, componets are not supported (e.g. <Table>)
*/
export default {
name: 'DatatableCGU',
props: {
/** datatables options object */
options: { type: Function, "default": ()=>{} },
/** callback that receives the datatable instance as param */
dtInstance: Function
},
data(){
return { datatables : null}
},
mounted() {
const dtInstance = $(this.$refs.tableElement).DataTable(this.options());
this.datatables = dtInstance;
if (this.dtInstance) {
this.dtInstance(dtInstance);
}
this.$root.$on('filtrar', this.refresh);
},
destroyed() {
$(this.$refs.tableElement).DataTable({destroy: true});
},
methods: {
refresh(filtros) {
this.datatables.ajax.reload();
}
}
}
</script>
On another component, i use this passing a datatables options with some custom renders on columns properties:
...
methods: {
getOptions(){
let options = this.getDefaultOptions();
options.ajax.url = "/api/auth/usuarios";
options.filtrador = this.filtrador;
options.columns = [
this.colunaDeSelecao(this.modoPopup)
,{name: "cpf", data: "cpf", title: "CPF"}
,{name: "nome", data: "nome", title: "Nome"}
,{name: "email", data: "email", title: "E-mail"}
,{name: "id", data: "id", title: "Ações", visible: !(this.modoPopup), sortable:false, className:"dt-center", width: "200px", render: function(data, type, row) {
return `<span class='btn-group btn-group-sm'>
<button id='btnAlternar__${data}' data-id='${data}' class='btn btn-${row.ativo?"danger":"success"}' data-toggle='tooltip' title='${row.ativo?"Inativar":"Ativar"}'><i class='fas fa-power-off'></i></button>
<a href='${window.$baseURL}auth/usuarios/${data}' class='btn btn-warning' data-toggle='tooltip' title='Editar'><i class='far fa-edit'></i></a>
</span>`;
}}
];
options.initComplete = () =>{
this.getDefaultOptions().initComplete();
this.criarTogglersSituacao();
};
return options;
}
...
If you notice the last column render creates a <a href='${window.$baseURL}auth/usuarios/${data}' ...
that obviously isn't a router-link and doesn't trigger vue router properly, causing an undesired page refresh.
I need the link to do a router push instead of a page refresh. How is this possible?
Upvotes: 1
Views: 1147
Reputation: 16089
There is no good answer to that problem. datatables
is not really compatible with Vue.js. With Vue, the usual way to go would be to pass your reactive HTML structure within a slot to such a library. Because datatables
requires you to use a render
function and return static HTML as a string, you cannot pass any JavaScript logic along.
The main problem is that you need to pass an event from the link tag to the Vue component. One approach would be to pass HTML in the render function which then can be selected with a specific selector (e.g. adding a class). You also need to add the link data/the item's ID to the HTML element (e.g. with a data-link=""
attribute). When datatables
has finished rendering, you can add a click listener to all the links. This click listener handler function needs to read the link/ID of the link and pass it to the router. Then, you can use Vue's router.push()
function.
When you are implementing a solution with the above approach, make sure to assign and remove the click listeners depending on the lifecycle events of datatables
. It might be necessary to add and remove the listeners on each page switch.
Upvotes: 1