/vue-datatables-net

Vue jQuery DataTables.net wrapper component

Primary LanguageVueMIT LicenseMIT

vue-datatables-net

Vue jQuery DataTables.net wrapper component

This library is a Vue 2 wrapper for jQuery DataTables. It's a tiny wrapper that doesn't include anything, not even the datatables.net core library.

Development

This library uses the NodeJS library laravel-mix to simplify build and packaging.

Requirement: Install NodeJS, NPM

Then:

git clone https://github.com/niiknow/vue-datatables-net
cd vue-datatables-net
npm install

To run locally (automatically launch firefox):

npm run watch

To build library for npm publish:

npm run build

This library is available on NPM, to install:

npm install vue-datatables-net

Usage

This library default configuration and provide example for use with bootstrap4 styling. Though, it allow for complete flexibility of customization with any other jQuery DataTables supported theme.

Example of imports for Bootstrap 4:

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel="stylesheet" href='https://cdn.datatables.net/1.10.19/css/dataTables.bootstrap4.min.css'>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>

<script>
import VdtnetTable from 'vue-datatables-net'
import 'datatables.net-bs4'

/*
// you can import these on a needed basis
// this import all buttons that we need, for
// use with opts: { buttons: ['csv', 'print', ...]}
import 'datatables.net-buttons/js/dataTables.buttons.js';
import 'datatables.net-buttons/js/buttons.html5.js';
import 'datatables.net-buttons/js/buttons.print.js';
import 'datatables.net-responsive/js/dataTables.responsive.js';

// import any datatables.net extension as you would when using it raw
import 'datatables.net-buttons-bs4'
import 'datatables.net-responsive-bs4'
import 'datatables.net-fixedheader-bs4'
import 'datatables.net-scroller-bs4';
import 'datatables.net-select-bs4';

// import any styles to support the packages you import above
import 'datatables.net-bs4/css/dataTables.bootstrap4.min.css';
import 'datatables.net-buttons-bs4/css/buttons.bootstrap4.min.css';
import 'datatables.net-responsive-bs4/css/responsive.bootstrap4.min.css';
import 'datatables.net-scroller-bs4/css/scroller.bootstrap4.min.css';
import 'datatables.net-select-bs4/css/select.bootstrap4.min.css';
*/
</script>

See example App

Example App demonstrate how to pass in overrides for our jQuery DataTable default options - https://github.com/niiknow/vue-datatables-net/blob/master/example/App.vue

NOTE: Our example use a free API endpoint from typicode, which is simply a JSON endpoint. As a result, we needed to define a dataSrc wrapper like so:

ajax: {
  url: 'https://jsonplaceholder.typicode.com/users',
  dataSrc: (json) => {
    return json
  }
}

Of course, for your implementation, simply use a server-side compatible parser. Below are some jQuery DataTables server-side parsers:

Documentation

Since it's a wrapper, all/most features are provided by the jQuery DataTables library.

Parameters

Our component parameters:

  props: {
    /**
     * Set the table classes you wish to use, default with bootstrap4
     * but you can override with: themeforest, foundation, etc..
     *
     * @type String
     */
    className: {
      type: String,
      default: 'table table-striped table-bordered nowrap w-100'
    },
    /**
     * the options object: https://datatables.net/manual/options
     *
     * @type Object
     */
    opts: {
      type: Object
    },
    /**
     * List all fields to be converted to opts columns
     *
     * @type Object
     */
    fields: {
      type: Object
    },
    /**
     * Pass in DataTables.Net jQuery to resolve any conflict from
     * multiple jQuery loaded in the browser
     *
     * @type Object
     */
    jquery: {
      type: Object
    },
    /**
     * The select-checkbox column index (start at 1)
     * Current implementation require datatables.net-select
     *
     * @type Number
     */
    selectCheckbox: {
      type: Number
    },
    /**
     * Provide custom local data loading.  Warning: this option has not been
     * thoroughly tested.  Please use ajax and serverSide instead.
     *
     * @type Function
     */
    dataLoader: {
      type: Function
    },
    /**
     * true to hide the footer of the table
     *
     * @type Boolean
     */
    hideFooter: {
      type: Boolean
    },
    /**
     * The details column configuration of master/details.
     *
     * @type {Object}
     */
    details: {
      type: Object
    }
  }

fields is an schema object that identify all datatables.net columns, example:

Example:

fields: {
  _id: { label: "ID" },
  title: { label: "Title", searchable: true, sortable: true },
  type: { label: "Type" }
}

Field properties

  • label Title for display
  • searchable true to enable search of field
  • sortable false to disable sorting
  • name to override the name
  • visible false to hide
  • width to provide custom width
  • className set column class names
  • defaultContent provide default html when no data available
  • render custom cell rendering function https://datatables.net/reference/option/columns.render
  • template simple vue template for the field. See example App.
  • defaultOrder null, asc/desc - the default/initial sort order

It is important to understand why one should use fields and not opts.columns. Though, fields is optional, you can simply pass opts.columns definition if you do not wish to use fields.

One Purpose of this component is to extend jQuery DataTables function and features, example:

  • Simplification of features configuration, such as select-checkbox column, custom action buttons, and/or future Vue specific features.
  • Allow for customizable table heading on a per-column basis; thereby, not having to define all html for each column header.
  • Ability to have simple template field so you can pass schema JSON from static file or some API, instead of requiring to define a javascript render function. Though, the render function would provide best performance.
  • Having schema also allow future features, such as: support of editable column/cell.

Additional Headers

Many server-side usage require CSRF and/or API token headers. Since jQuery DataTables options are completely exposed as opts, simply use the native method per jQuery DataTables example

i.e, something like:

opts: {
  'ajax': {
    'url': url,
    'type': 'GET',
    'beforeSend': function (request) {
        request.setRequestHeader("token", token);
    }
  }
}

// or as headers parameter
opts: {
  'ajax': {
    'url': url,
    'type': 'GET',
    'headers': {
      'CSRFToken': TOKEN
    }
  }
}

// or as query parameter
opts: {
  'ajax': {
    'url': url,
    'type': 'GET',
    'data': function ( d ) {
      d.CSRFToken = TOKEN;
    }
  }
}

If you haven't already guessed, ajax is basically the signature of jQuery.ajax, which can be seen in this jQuery DataTables ajax pipeline code demonstration.

Row Action Buttons

Use data-action attribute to automatically wire up any action button/elements. To render action button/element in a row, simply define dummy field like so:

actions: {
  label: 'Actions',
  defaultContent: '<a href="javascript:void(0);" data-action="edit" class="btn btn-primary btn-sm"><i class="mdi mdi-square-edit-outline"></i> Edit</a>' +
    '<span data-action="delete" class="btn btn-danger btn-sm"><i class="mdi mdi-delete"></i> Delete</span>'
}

Reload method and reloaded event

Allow you to refresh ajax content after some event. Let say you have something like this:

<template>
  <div id="app">
    <vdtnet-table
      :fields="fields"
      :opts="options"
      ref="table"
      @delete="doAjaxDelete"
      @reloaded="doSomethingAfterReload"
    />
  </div>
</template>
<script>
// ... component top ...
  methods: {
    doAjaxDelete(data, row, tr, target) {
      // do some ajax delete
      // then reload after ajax complete
      this.$refs.table.reload()
    },
    doSomethingAfterReload(data, table) {
      // some something after data loaded from server
    }
  }
// ... component bottom ...

Customizable table head (th) columns

Let say you have a column description, you can provide table head template for the description column like so:

<template slot="HEAD_description">
  <h1>desc</h1>
</template>

dom (Searching and Toolbar)

dom configuration defines how jQuery DataTables components are rendered - https://datatables.net/reference/option/dom

Our default configuration compatible with Bootstrap4 is:

"tr<'row vdtnet-footer'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'pl>>"

This is based on the configuration lftiprB, also see: https://datatables.net/reference/option/dom

Note, we do not include toolbar buttons (B) or search control (s). This is because we defer these functions to you (the User). Toolbar Buttons are client-side; and since we do not use client-side, we don't need these buttons. We expose a search method on vdtnet-table so you can use this method to perform search.

Simply create your own Buttons for server-side exports, bulk, and/or other things. Create your own search control and use the search method. See example App. All these things are now Vue natives.

Though, if you really insists on using these client-side controls, simply override the default opts.dom and opts.buttons with your own settings.

getServerParams method

This function return the parameters last used by our server-side endpoint. It allow you to use for server-side export API call. Example:

const parms = this.$refs.table.getServerParams()
parms.export = 'csv'
// boom export
const url = 'export.php?' + $.param(data)
window.open(url)

Responsive

  1. In Bootstrap4, there's a class called table-responsive that wrap the table at each screen breakpoint. We apply this class on our wrapper div to make the table scroll horizontally.

  2. Alternatively, you can set options.responsive = true to use jQuery DataTable responsive plugin. WARNING: This plugin does not play well with select-checkbox, master-details, and many other features. It is recommended to use option 1 above.

Master-details pattern

details configuration allow you to create template for displaying details row in Master-details pattern. Schema:

{
  index: 'a number (start at 1) representing the column position',
  template: 'the template where {{ data.column }} is the item/row data',
  render: 'provide a custom render function as alternative to template'
}

Tips

If you're like us, you want to write as little code as possible; as in, application of the DRY Principle. This mean the UI has a standard look/feel/behavior; where toolbar, search, and other controls are place at specific location. So this mean you want to wrap this component inside your own component? Our sample App give you a good idea on how to start. Below are a few things to consider:

  1. Identify all properties of the new component and howto translate into this component. Example: hidePageLength -> opts.lengthChange, hideQuickSearch -> v-if on quickSearch form, hideToolbar -> v-if on toolbar div, etc...
  2. Identify methods to wrap, i.e. your component API: reload, getServerParams, etc...
  3. Wrap individual action events you want to expose, or simply wrap with v-on="$listeners" to pipe all events from this component to your component.

License

The MIT License (MIT). Please see License File for more information.