Skip to content

Instantly share code, notes, and snippets.

@saniyathossain
Created February 18, 2020 16:54
Show Gist options
  • Save saniyathossain/f98d57fd60c66ce79172faad6464cdb4 to your computer and use it in GitHub Desktop.
Save saniyathossain/f98d57fd60c66ce79172faad6464cdb4 to your computer and use it in GitHub Desktop.
Datatables With Vue JS, TypeScript, Bootstrap 4, Parcel JS
<!-- Path: components/DataTable.vue -->
<template>
<table class="table table-light table-striped table-bordered table-responsive nowrap">
<thead>
<tr>
<th v-for="column in parameters.columns" v-html="column.title" :key="column.name"></th>
</tr>
</thead>
<tfoot v-if="footer">
<tr>
<th v-for="column in parameters.columns" v-html="column.footer" :key="column.name"></th>
</tr>
</tfoot>
</table>
</template>
<script lang="ts">
require('datatables.net')(window, $)
require('jszip')(window, $)
// require('pdfmake')(window, $)
require('datatables.net-bs4')(window, $)
// require('datatables.net-autofill-bs4')(window, $)
require('datatables.net-buttons-bs4')(window, $)
// require('datatables.net-buttons/js/buttons.colVis.js')(window, $)
require('datatables.net-buttons/js/buttons.html5.js')(window, $)
require('datatables.net-buttons/js/buttons.print.js')(window, $)
// require('datatables.net-plugins/pagination/select.js')(window, $)
// require('datatables.net-colreorder-bs4')(window, $)
// require('datatables.net-fixedcolumns-bs4')(window, $)
// require('datatables.net-fixedheader-bs4')(window, $)
// require('datatables.net-keytable-bs4')(window, $)
// require('datatables.net-responsive-bs4')(window, $)
// require('datatables.net-rowgroup-bs4')(window, $)
// require('datatables.net-rowreorder-bs4')(window, $)
// require('datatables.net-scroller-bs4')(window, $)
// require('datatables.net-select-bs4')(window, $)
// GLOBAL DATATABLES ERROR MODE
$.fn.dataTableExt.sErrMode = 'console'
$.fn.dataTableExt.oApi._fnLog = function (oSettings, iLevel, sMesg, tn) {
var sAlert = (oSettings === null) ? 'DataTables warning: ' + sMesg : 'DataTables warning (table id = " + oSettings.sTableId + "): ' + sMesg;
if (tn) {
sAlert += '. For more information about this error, please see ' + 'http://datatables.net/tn/' + tn
}
if (iLevel === 0) {
if ($.fn.dataTableExt.sErrMode == 'alert') {
// alert(sAlert)
} else if ($.fn.dataTableExt.sErrMode == 'thow') {
throw sAlert
} else if ($.fn.dataTableExt.sErrMode == 'console') {
console.error(sAlert)
} else if ($.fn.dataTableExt.sErrMode == 'mute') {
}
return;
} else if (console !== undefined && console.log) {
console.log(sAlert)
}
}
import { Component, Vue, Prop } from 'vue-property-decorator'
import { mixins } from 'vue-class-component'
import Services from '~mixins/Services'
@Component({
name: 'DataTable'
})
export default class DataTable extends mixins (Services) {
@Prop({ default: false }) footer: boolean
@Prop({ default: false }) ajax: string
@Prop(Array) columns: array
@Prop(Array) columnDefs: array
@Prop(Object) options: object
@Prop(Object) dataTable: object
get parameters () {
const vm:any = this
return $.extend({
processing: true,
serverSide: true,
ajax: vm.ajax,
columns: vm.columns,
columnDefs: vm.columnDefs,
dom: '<"mrg0A pad0A col-md-2 pull-left"l><"col-md-6 text-center pull-left"B><"mrg0A pad0A col-md-3 text-right pull-right"f><"clearfix">rtip',
language: {
// processing: '<i class="fa fa-3x text-center fa-spin text-red ion-load-c loading-z-index"></i>',
// loadingRecords: '<i class="fa fa-3x text-center fa-spin text-red ion-load-c loading-z-index"></i>',
processing: vm.loading(),
loadingRecords: vm.loading(),
lengthMenu: '_MENU_',
search: '',
searchPlaceholder: 'Search Records...'
},
lengthMenu: [
[10, 25, 50, 75, 100, -1],
['10', '25', '50', '75', '100', 'All']
],
displayLength: 10,
destroy: true,
deferRender: true,
fixedHeader: {
header: true,
footer: true
},
keys: true,
// pagingType: 'listbox',
// pagingType: 'select',
buttons: {
dom: {
button: {
tag: 'button',
className: 'btn btn-sm btn-primary',
exportOptions: {
columns: 'th:not(.no-export)'
}
}
},
buttons: [{
extend: 'copyHtml5',
text: '<i class="far fa-copy"></i> Copy',
titleAttr: 'Copy to clipboard'
}, {
extend: 'excelHtml5',
text: '<i class="far fa-file-excel"></i> Excel',
titleAttr: 'Export to excel'
}, {
extend: 'csvHtml5',
text: '<i class="far fa-file-excel"></i> CSV',
titleAttr: 'Export to CSV'
}, {
extend: 'pdfHtml5',
text: '<i class="fa fa-file-pdf-o"></i> PDF',
titleAttr: 'Export to PDF',
orientation: 'landscape',
pageSize: 'A4'
}, {
extend: 'print',
text: '<i class="fa fa-print"></i> Print',
titleAttr: 'Print',
autoPrint: true
}]
},
createdRow(...args) {
vm.$emit('created-row', ...args)
},
drawCallback(...args) {
vm.$emit('draw', ...args)
},
footerCallback(...args) {
vm.$emit('footer', ...args)
},
formatNumber(...args) {
vm.$emit('format', ...args)
},
headerCallback(...args) {
vm.$emit('header', ...args)
},
infoCallback(...args) {
vm.$emit('info', ...args)
},
initComplete(...args) {
vm.$emit('init', ...args)
},
preDrawCallback(...args) {
vm.$emit('pre-draw', ...args)
},
rowCallback(...args) {
vm.$emit('draw-row', ...args)
},
stateLoadCallback(...args) {
vm.$emit('state-load', ...args)
},
stateLoaded(...args) {
vm.$emit('state-loaded', ...args)
},
stateLoadParams(...args) {
vm.$emit('state-load-params', ...args)
},
stateSaveCallback(...args) {
vm.$emit('state-save', ...args)
},
stateSaveParams(...args) {
vm.$emit('state-save-params', ...args)
},
}, this.options)
}
mounted () {
this.renderDatatable()
}
renderDatatable () {
this.dataTable = $(this.$el).DataTable(this.parameters)
}
}
</script>
<!-- Path: mixins/DataTable.vue -->
import { Vue, Component, Prop } from 'vue-property-decorator'
@Component
export default class Datatables extends Vue {
@Prop(String) title: string
@Prop(String) createRoutePath: string
@Prop(Array) tableColumns: array
@Prop(Array) tableColumnDefs: array
@Prop(String) url: string
created () {
this.getCreateRoutePath()
this.getTableCoulmns()
}
getCreateRoutePath () {
this.createRoutePath = this.$router.currentRoute.path + '/create'
}
getTableCoulmns () {
this.tableColumns = [{
data: 'id',
name: 'id',
title: 'ID#',
searchable: true,
sortable: true
}, {
data: 'name',
name: 'name',
title: this.title + ' Name',
searchable: true,
sortable: true
}, {
data: 'action',
name: 'action',
title: 'Action',
searchable: false,
sortable: false,
className: 'no-export'
}]
}
getTableCoulmnDefs () {
this.tableColumnDefs = [{
render: function (data, type, full, meta) {
return '<span class="badge badge-primary">' + data + '</span>'
},
targets: 0
}]
}
}
<!-- Path: views/index.vue -->
<template>
<div class="animated fadeIn">
<div class="row">
<div class="col-12">
<div class="card card-accent-primary card-inverse">
<div class="card-header">
{{ title }}
<router-link :to="createRoutePath" class="btn btn-sm btn-primary pull-right">
<i class="fas fa-plus"></i> New {{ title }}
</router-link>
</div>
<div class="card-block">
<data-table
:columns="tableColumns"
:ajax="url"
>
</data-table>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import Component, { mixins } from 'vue-class-component'
import dataTable from '~components/DataTable'
// import dataTableIndex from '~/components/DataTableIndex'
import Datatables from '~mixins/Datatables'
@Component({
name: 'Menu',
components: {
dataTable
}
})
export default class MenuIndex extends mixins (Datatables) {
title: string = 'Menu',
resource: string = 'menus',
url: string = '/api/menus'
getTableCoulmns() {
this.tableColumns = [{
data: 'id',
name: 'id',
title: 'ID#',
searchable: true,
sortable: true
}, {
data: 'name',
name: 'name',
title: this.title + ' Name',
searchable: true,
sortable: true
}, {
data: 'display_name',
name: 'display_name',
title: this.title + ' Display Name',
searchable: true,
sortable: true
}, {
data: 'action',
name: 'action',
title: 'Action',
searchable: false,
sortable: false,
className: 'no-export'
}]
}
}
</script>
{
"name": "Test",
"version": "1.0.0",
"description": "Test Appplication",
"main": "resources/client/vue/main.ts",
"scripts": {
"test": "test",
"start": "parcel build resources/client/vue/main.ts -d public/build",
"build": "cross-env NODE_ENV=production parcel build resources/client/vue/main.ts -d public/build",
"watch": "cross-env NODE_ENV=production parcel watch resources/client/vue/main.ts -d public/build",
"serve": "cross-env NODE_ENV=production parcel serve resources/client/vue/main.ts"
},
"author": "saniyat hossain",
"license": "MIT",
"devDependencies": {
"@vue/component-compiler-utils": "^2.0.0",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-plugin-dynamic-import-node": "^2.1.0",
"babel-preset-env": "^1.7.0",
"node-sass": "^4.9.0",
"parcel-bundler": "^1.10.1",
"posthtml": "^0.11.3",
"tslint": "^5.10.0",
"typescript": "^3.1.1",
"vue-class-component": "^7.0.1",
"vue-hot-reload-api": "^2.3.1",
"vue-property-decorator": "^8.0.0",
"vue-router": "^3.0.1",
"vue-template-compiler": "^2.5.16",
"vuex": "^3.0.1"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^5.2.0",
"@types/node": "^11.10.5",
"add": "^2.0.6",
"axios": "^0.18",
"basscss": "8.0.10",
"bootstrap-vue": "^2.0.0-rc.11",
"cross-env": "^5.2.0",
"datatables.net-autofill-bs4": "^2.3.2",
"datatables.net-bs": "^1.10.19",
"datatables.net-bs4": "^1.10.19",
"datatables.net-buttons-bs": "^1.5.3",
"datatables.net-buttons-bs4": "^1.5.3",
"datatables.net-colreorder-bs4": "^1.5.1",
"datatables.net-fixedcolumns-bs4": "^3.2.6",
"datatables.net-fixedheader-bs4": "^3.1.5",
"datatables.net-keytable-bs4": "^2.4.1",
"datatables.net-plugins": "^1.10.18",
"datatables.net-responsive-bs4": "^2.2.3",
"datatables.net-rowgroup-bs4": "^1.0.4",
"datatables.net-rowreorder-bs4": "^1.2.5",
"datatables.net-scroller-bs4": "^1.5.1",
"datatables.net-select-bs4": "^1.2.7",
"element-ui": "^2.4.8",
"ionicons": "^4.4.4",
"jquery": "^3.2",
"js-cookie": "^2.2.0",
"jszip": "^3.1.5",
"lodash": "^4.17.11",
"pdfmake": "^0.1.38",
"sweetalert": "^2.1.0",
"vue": "^2.5.16",
"vuex-class": "^0.3.1",
"vuex-router-sync": "^5.0.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment