Skip to content

Vue component for rendering tables used in ENA projects

License

Notifications You must be signed in to change notification settings

myENA/vue-table

Folders and files

NameName
Last commit message
Last commit date

Latest commit

28bcbcc · Mar 13, 2025
May 29, 2020
Mar 13, 2025
May 28, 2020
Nov 11, 2018
Mar 13, 2025
Jul 1, 2021
Nov 11, 2018
Nov 11, 2018
Nov 11, 2018
Nov 27, 2020
Jan 19, 2019
Nov 11, 2018
Nov 11, 2020
Jan 19, 2019
Feb 1, 2019
May 28, 2020
May 5, 2020
Nov 11, 2018
Jan 19, 2019
Mar 13, 2025
Mar 13, 2025
Nov 11, 2018
Jan 19, 2019
Nov 11, 2018
May 5, 2020

Repository files navigation

vue-table

CircleCI (all branches) npm (scoped) NpmLicense npm bundle size (minified + gzip) David David

What's this

Components to render a table using client or remote data

Install

npm install @myena/vue-table

Dependencies

  • Vue 2
  • Bootstrap 3
  • FontAwesome 4

Demo

https://myena-vue-table.netlify.app/

Vue Client Table

Vue component for rendering a client side table with pagination, grouping, sorting, filtering, details row. Entire table data should be given to the table and will be paginated client side. Data can come from a Vuex store.

Usage:

<EnaTableClient :columns="columns" :options="options" :data="data" :loading="loading">
  <my-custom-filter-component slot="filter" v-on:search="search"></my-custom-filter-component>
  <span slot="__group_meta" slot-scope="{ data }">
    <strong><span v-html="data.label"></span> (Total in group: {{data.total}})</strong>
  </span>
  <template slot="heading_column1">
    <div>Custom heading of column1</div>
  </template>
  <template slot="column_column1" slot-scope="{ row }" >
    <span><i v-if="row.column2 === 'disable'" class="fa fa-ban"></i> {{row.column1}}</span>
  </template>
  <template slot="details_row" slot-scope="{ row }">
    <div>Div for details (expanded) row</div>
  </template>
</EnaTableClient>

As plugin (or in Browser)

// this will create the global (window) object "EnaTableClient"
import '@myena/vue-table/dist/EnaTableClient';
// or include as script in html : <script type="text/javascript" src="node_modules/@myena/vue-table/dist/EnaTableClient/index.js"></script>
// registers the component globally

// in the view that contains the table
const MyView = new Vue({
  data() {
    // Define properties
    return {
      /**
       * List of objects to present in the table
       *
       * @member
       * @type {Array}
       */
      data: Array,
      /**
       * List of keys to use from each object (table columns)
       *
       * @type {Array}
       */
      columns: Array,
      /**
       * The filter object. If updated will filter the results by the value
       *
       * @type {Object}
       */
      filter: {
        type: Object,
        default: () => ({
          // The search query string. If updated will filter the results by the value
          keyword: '',
        }),
      },
      /**
       * Loading indicator. If true, will display the `loadingMsg` instead of the body
       * @type {Boolean}
       */
      loading: {
        type: Boolean,
        default: false,
      },
      /**
       * Options for the table
       *
       * @inner
       * @type {Object}
       */
      options: {
        /**
         * Classes to use on various elements
         *
         * @inner
         * @type {Object}
         */
        classes: {
          wrapper: 'table-responsive',
          table: 'table',
          formControl: 'form-control',
          sort: {
            none: 'fa fa-sort',
            ascending: 'fa fa-sort-asc',
            descending: 'fa fa-sort-desc',
          },
          pagination: {
            wrapper: 'pagination',
            info: 'info form-inline',
            first: 'fa fa-angle-double-left',
            prev: 'fa fa-angle-left',
            next: 'fa fa-angle-right',
            last: 'fa fa-angle-double-right',
          },
          group: {
            show: 'fa fa-chevron-right',
            hide: 'fa fa-chevron-down',
          },
        },
        /**
         * Key-value pairs with the headings to overwrite (label to display)
         * can also be overwritten with slot: "heading_colname"
         *
         * @inner
         * @type {Object}
         */
        headings: {},
        /**
         * Key-value pairs with templates (components) for the column value
         *
         * @type {Object}
         */
        templates: {},
        /**
         * Key-value pairs with custom search function per column,
         * or false to disable search for that column
         *
         * @type {Object}
         */
        search: {},
        /**
         * Field to group by - key name
         *
         * @default
         * @type {Boolean|String}
         */
        groupBy: false,
        /**
         * Expand/collapse groups
         *
         * @default
         * @type {Boolean}
         */
        toggleGroups: false,
        /**
         * Object of data to use for each group "header" (key is the group value)
         *
         * @type {Object}
         */
        groupMeta: {},
        /**
         * Required, unique identifier
         *
         * @default
         * @type {String}
         */
        uniqueKey: 'id',
        /**
         * show extra row for each row with details
         *
         * @default
         * @type {Boolean}
         */
        detailsRow: false,
        /**
         * Texts
         *
         * @type Object
         */
        text: {
          /**
           * Text to show when row can be expanded
           * @type {String}
           */
          expand: 'Show details',
          /**
           * Text to show when row can be collapsed
           * @type {String}
           */
          collapse: 'Hide details',
          /**
           * Message to show when there is no data
           * @type {String}
           */
          noData: 'No data to show',
          /**
           * Message to show when no results are found for the search
           * @type {String}
           */
          emptyResults: 'No results for this filter',
          /**
           * Message to show when no results are found for the search
           * @type {String}
           */
          loading: 'Loading ...',
          /**
           * Text to show for pagination helper buttons
           * @type {Object}
           */
          pagination: {
            next: '',
            last: '',
            info: {
              showing: 'Showing %s to %s of %s rows.',
              records: 'records per page',
              noRows: 'No rows to display',
            },
          },
        },
        /**
         * empty object to disable sorting for all,
         * or define what columns are sortable; defaults to all sortable
         *
         * @default
         * @type {true|Object}
         */
        sortable: true,
        /**
         * false, to disable pagination - show all; defaults to true
         *
         * @default
         * @type {Boolean}
         */
        pagination: true,
        /**
         * number of items per page
         *
         * @default
         * @type {Number}
         */
        perPage: 10,
        /**
         * How many pages to show in the paginator. Odd number
         *
         * @default
         * @type {Number}
         */
        pageInterval: 7,
        /**
         * values to show in the selector of items per page
         *
         * @default
         * @type {Array}
         */
        perPageValues: [1, 2, 5, 10, 20, 50],
        /**
         * Is the table editable (eg: can select value)
         * @type {Boolean}
         */
        editable: false,
        /**
         * List of columns that should be disabled for click to select/deselect
         * @type {Array}
         */
        nonSelectableColumns: [],
        /**
         * Object (key, order) to sort table by on first load (on created)
         * @type {Object}
         */
        sortBy: {
          column: null,
          order: null,
        },
        /**
         * The collator used for sorting
         * @type {Intl.Collator}
         */
        sortCollator: new Intl.Collator('en', {
          numeric: true,
          sensitivity: 'base',
        }),
      },
    };
  },
  // OR use computed properties instead
  computed: {
    data() {
      return this.$store.state.myListData; // or any other source that has all data
    },
  },
  methods: {
    search(filter) {
      this.searchQuery = filter.keyword;
    },
  },
  watch: {
    data(data) {
      // set the group metas when data changes
      // groupColumn is the same as the one used for 'groupBy' option
      this.options.groupMeta = data.reduce((groupMeta, r) => {
        if (!groupMeta[r.groupColumn]) {
          groupMeta[r.groupColumn] = {
            label: r.groupColumn,
            total: 0,
          };
        }
        groupMeta[r.groupColumn].total += 1;
        return groupMeta;
      }, {});
    },
  },
});

As module/local component

import { Client } from '@myena/vue-table';

// in the view that contains the table
const MyView = new Vue({
  components: {
    ClientTable: Client,
  },
  data() {
    return {
      columns: ['column1', 'column2'],
      options: {
      },
    };
  },
  computed: {
    data() {
      return this.$store.state.myListData; // or any other source that has all data
    },
  },
});

Vue Server Table

Vue component for rendering a table that loads data from the server, with pagination, sorting, filtering, details row. It doesn't support grouping.

Usage:

<EnaTableServer :columns="columns" :options="options" ref="serverTable">
  <div slot="filter">
    <input placeholder="Search by name" v-model="options.filter.name"/>
    <button @click="filter">Find</button>
  </div>
  <template slot="heading_column1">
    <div>Custom heading of column1</div>
  </template>
  <template slot="column_column1" slot-scope="{ row }" >
    <span><i v-if="row.column2 === 'disable'" class="fa fa-ban"></i> {{row.column1}}</span>
  </template>
  <template slot="details_row" slot-scope="{ row }">
    <div>Div for details (expanded) row</div>
  </template>
</EnaTableServer>
import axios from 'axios';
import Qs from 'qs';
import { Server: ServerTable } from '@myena/vue-table';

const myServerTable = {
  extends: ServerTable,
  methods: {
    /**
     * Override the fetch method
     */
    async fetch(params) {
      const { data } = await axios.get(this.url, {
        params: Object.assign({}, params, {
          filter: this.options.filter,
        }),
        paramsSerializer(p) {
          return Qs.stringify(p, { arrayFormat: 'brackets' });
        },
      });
      return data;
    },
    /**
     * Override the parse method to return `data` and `total` fields
     */
    parse({ list, total }) {
      return {
        data: list,
        total,
      };
    },
  },
};

export default {
  name: 'app',
  components: {
    ServerTable: myServerTable,
  },
  data: () => ({
    columns: ['name', 'capital', 'population'],
    url: 'https://us-central1-vue-myena-table.cloudfunctions.net/countries',
    options: {
      perPage: 5,
      uniqueKey: 'alpha3Code',
      // not handled by the component
      // added here for easier access in the overridden fetch function
      filter: {
        name: null,
      },
    },
  }),
  methods: {
    filter() {
      // call component loadData, which sets some params then calls fetch (above)
      this.$refs.serverTable.loadData();
    },
  },
};

About

Vue component for rendering tables used in ENA projects

Resources

License

Stars

Watchers

Forks

Packages

No packages published