Vue - Table Component

can be use for static and dynamic content

by Roman Joseph Rimorin

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://cdn.rawgit.com/matfish2/vue-pagination-2/controlled-component/dist/vue-pagination-2.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<div id="app">
  <div class="panel panel-default">
      <div class="panel-heading">Example Grid Table in VueJS</div>
      <div class="panel-body">
          <grid-component :columns="usersGrid.columns" :data="usersGrid.data" :filter-params="params" :url="usersGrid.url" ordering>
              <template slot="checkbox" slot-scope="item">
                  <input type='checkbox' style='-ms-transform: scale(1); -moz-transform: scale(1); -webkit-transform: scale(1); -o-transform: scale(1);'>
              </template>
              <template slot="actions" slot-scope="item">
                  <button type='button' class='btn fa fa-copy' v-on:click="log(item)" :data-item="item" title="Copy"></button>
                  <button type='button' class='btn fa fa-pencil' v-on:click="log(item)" :data-item="item" title="Edit"></button>
                  <button type='button' class='btn fa fa-trash' v-on:click="log(item)" :data-item="item" title="Delete"></button>
              </template>
          </grid-component>
      </div>
  </div>
</div>

<div id="grid-template" class="hidden">
    	<div class="col-md-12">
    	    <div class="row">
    	        <div class="col-sm-12 col-md-6">
    	            <label style="font-weight: normal; text-align: left; white-space: nowrap;">
    	                Show <select class="form-control" v-model="perpage" style="width: auto; display: inline-block;">
    	                    <option v-for="length in lengthMenu" v-bind:value="length">
    	      ...

CSS

body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
  transition: all 0.2s;
}

li {
  margin: 8px 0;
}

h2 {
  font-weight: bold;
  margin-bottom: 15px;
}

del {
  color: rgba(0, 0, 0, 0.3);
}

JavaScript

Vue.component("grid-component",
    {
        template: "#grid-template",
        props: {
            columns: Array,
            data: {
                type: Array,
                default: function() { return [] }
            },
            filterParams: Object,
            initData: Boolean,
            lengthMenu: {
                type: Array,
                default: function () { return [5, 10, 25, 50] }
            },
            ordering: Boolean,
            serverSide: Boolean,
            url: String
        },
        data: function () {
            var sortOrders = {}
            this.columns.forEach(function (column) { // get sort order
                sortOrders[column.name] = 1;
            });
            // return v2 data props
            return {
                currentPage: 1,
                perpage: 5, // length of the per page
                searchQuery: "",
                sortKey: "",
                sortOrders: sortOrders,
                serverSideData: [],
                totalRecords: 0
            };
        },
        components: {
            Pagination
        },
        computed: {
            filteredData: function () { // computes data to be shown in the grid.
                const vm = this;

                // if the table is serverside processing then return back the filtered data...
                // sorting and paging happens in the server side.
                if (vm.serverSide)
                    return vm.filterRecords();

                // this statements will be executed when data is eager loaded...
                let data = vm.filterRecords();
                
                const sortKey = vm.sortKey;
                const order = vm.sortOrders[sortKey] || 1;
                if (sortKey) {
                    data = data.slice().sort(function (a, b) {
                        a = a[sortKey];
                        b = b[sortKey];
                        return (a === b ? 0 : a > b ? 1 : -1) * order;
      ...