npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@andresouzaabreu/vue-data-table

v3.3.4

Published

A Vue plugin that adds advanced features to an HTML table

Downloads

2,791

Readme

VUE DATA TABLE

VueDataTable is a Vue plugin that adds advanced features to an HTML table. It was inspired by DataTable jQuery Plugin, but it was written from scratch using Vue.

Table of contents

  1. Features
  2. Demo
  3. Getting started
  4. Configuration
  5. License
  6. Versioning
  7. Contributing
  8. Authors

Features

  • Multiple Column Sorting
  • Pagination
  • Search Filter
  • Export data (XLS, JSON, CVS, or TXT)
  • Custom component cell
  • Custom Text

Demo

The best way to see if a package suits your needs is by viewing and editing a demo project. Here are some code playgrounds in which you can test VueDataTable.

Both Demo 1 and Demo 2 are from older versions of this plugin, but should still work with newer versions because the API didn't change much. Demo 3 is from the newest version and has an example of a custom footer component. Demo 4 implements mass-selection of rows using custom component and checkboxes. Demo 5 uses a custom loading component that is shown to the user while data is being loaded.

Getting started

Installation

npm install --save @andresouzaabreu/vue-data-table

Set up

import DataTable from "@andresouzaabreu/vue-data-table";
Vue.component("data-table", DataTable);

Don"t forget to add the style sheets

import "@andresouzaabreu/vue-data-table/dist/DataTable.css";

Use

<template>
    <div>
        <data-table v-bind="bindings"/>
    </div>
</template>
<script>
export default {
    computed: {
        bindings() {
            return {
                columns: [/*the columns*/]
                data: [/*the data*/]
                /* other props...*/
            }
        }
    },
}
</script>

Note Notice that v-bind will take all key-value pairs in the object (in this case, the bindings), and pass them as props to the VueDataTable. So, this is a shortcut to pass multiple props at once.

Configuration

Only data e columns are required. Other props are optional.

| prop | type | default | description | | --- | --- | --- | --- | | data | Array | - | Array of objects with the data to be displayed on the table | | columns | Array | - | Array of objects that specifies how to render each column. Optional if columnKeys is present. | | columnKeys | Array | - | Array of strings matching the object keys in data. This is discarded if columns is set. | | lang | String | en | The default language | | perPageSizes | Array | [10, 25, 50, 100] | The options for the number of rows being displayed per page | | defaultPerPage | Number | 10 | The default number of entries. If unset, then it will be the first value of perPageSizes | | isLoading | Bool | false | Whether table data is loading. Table rows are shown only if this value is set to false. | | loadingComponent | Object, String | - | VueJS component to be shown if isLoading is set to true | | showPerPage | Bool | true | Whether to show the PerPage component | | showEntriesInfo | Bool | true | Whether to show the EntriesInfo component | | showSearchFilter | Bool | true | Whether to show the SearchFilter component | | showPagination | Bool | true | Whether to show the Pagination component | | showDownloadButton | Bool | true | Whether to show the button to download the table's data | | tableClass | String | table table-striped table-hover | The table's HTML class attribute | | sortingMode | String | multiple | Whether to sort a single column or multiple columns at once | | sortingIndexComponent | Object, String | DataTableSortingIndex | VueJS component for the sorting index on sortable columns | | sortingIconComponent | Object, String | DataTableSortingIcon | VueJS component for the sorting icon on sortable columns | | footerComponent | Object, String | null | VueJS component for custom table footer | | allowedExports | Array | ["xls", "csv", "json", "txt"] | Formats the user can export the data to. Only four export types are available. |

Columns

| key | type | default | description | | --- | --- | --- | --- | | key | String | - | The key of the objects in the data prop. The value of the matching key will be displayed in a table cell | | title | String | titleCase(key) | The title to be displayed in the th element. If not specified, it will capitalize the key and then remove its dashes and underscores | | searchable | Bool | true | Whether to allow filtering the objects in data by matching the search text in the object's key | | sortable | Bool | true | Whether to allow sorting the column. It will use the key to sort the objects in the data | | type | String | string | Where to sort the column as a string or as a number. Allowed values are string and number. | | sortingFunction | Function | - | Custom function provided by the user to sort the column. | | index | Number | 0 | A higher index puts the column to the right of the table. A lower index puts the column to the left of the table. | | component | Object,String | - | Custom Vue Component provided by the user. This component should have a prop called data, which contains the data of current row. |

If columns is not defined, then columnKeys must be defined and it will be mapped to a columns array with the default parameters. Example:

// we can define the columns
config = {
    data: users,
    columns: [
        {
            key: "name",
        },
        {
            key: "email",
            title: "Email Address",
            sortable: false,
        },
        {
            key: "phone",
            sortable: false,
            searchable: false,
            /* this will make this column appear to the right of the table
            since its index is greater than others*/
            index: 100,
        },
        {
            key: "permissions",
            /* custom function sort users by which user has more permissions */
            sortingFunction: function(a, b) {
                // permissions is an array
                return a.permissions.length - b.permissions.length;
            },
            /* custom component to display the permissions */
            component: UserPermissionList,
        }
    ]
}

// or use columnKeys shortcut
config = {
    data: user,
    columnKeys: ["name", "email", "registered_at", "last_access_at"]
},

// which will take the default column and map the array into this
[
    {
        key: "name",
        title: "Name",
        sortable: true,
        searchable: true,
        index: 0
    },
    {
        key: "email",
        title: "Email",
        sortable: true,
        searchable: true,
        index: 0
    },
    {
        key: "registered_at",
        title: "Registered at",
        sortable: true,
        searchable: true,
        index: 0
    },
    {
        key: "last_access_at",
        title: "Last access at",
        sortable: true,
        searchable: true,
        index: 0
    },
]

Custom component

In the example above, we used a custom component called UserPermissionList. Below is a sample of that custom component.

<template>
    <div>
        List of permissions for the user {{ data.name }} :
        <ul>
            <li v-for="(permission, i) in data.permissions" :key="i">
                {{ permission }}
            </li>
        </ul>
    </div>
</template>
<script>
export default {
    name: "UserPermissionList",
    props: {
        data: {
            type: Object,
            required: true
        }
    }
}
</script>

Another example, using action buttons:

<template>
    <div class="action-buttons">
        <button class="btn btn-outline-success" @click="handleAction('view')">
            <i class="fa fa-eye"></i>
        </button>
        <button class="btn btn-outline-primary" @click="handleAction('edit')">
            <i class="fa fa-edit"></i>
        </button>
        <button class="btn btn-outline-dark" @click="handleAction('delete')">
            <i class="fa fa-trash"></i>
        </button>
    </div>
</template>
<script>
export default {
    name: "ActionButtons",
    methods: {
        handleAction(actionName) {
            /* when the user clicks a button, that will trigger a mutation on our Vuex store
            The mutation may show a form for editing a resource, or maybe a popup box asking
            the user to confirm deleting a resource, or open a new page for the user to view
            a resource.
             */
            this.$store.commit(actionName, this.data)
        }
    },
    props: {
        data: {
            type: Object,
            required: true,
        },
    },
};
</script>

Text

Currently, VueDataTable has support for three languages: English (en), Brazilian Portuguese (pt-br), and Spanish(es). The lang prop specifies in which language to display the text in our table.

If we want to add a custom text (maybe because there is no language support or because we want something else), we have to set it in the text prop.

The following table shows the texts we can customize and their default values for the English language.

| key | default | | --- | --- | | perPageText | "Show :entries entries" | | infoText | "Showing :first to :last of :total entries" | | infoFilteredText | "Showing :first to :last of :filtered (filtered from :total entries)" | | nextButtonText | "Next" | | previousButtonText | "Previous" | | paginationSearchText | "Go to page" | | paginationSearchButtonText | "GO" | | searchText | "search:" | | downloadText | "export as:" | | downloadButtonText | "DOWNLOAD" | | emptyTableText | "No matching records found" |

Note: Notice that the placeholders :first, :last, :total, and filtered will be automatically replaced with the proper numbers.

Example code:

parameters() {
    return {
        data: [/**/],
        columns: [/**/],
        text: {
            PerPageText: "Number of users per page :entries",
            infoText: "Displaying :first to :last of :total users",
            emptyTableText: "No users found :(",
        }
    }
}

Adding global custom language

If your lang is not yet supported, you can add a new language and use it in any VueDataTable instance as follow:

import { languageServiceProvider } from "@andresouzaabreu/vue-data-table";
const loremIpsumLanguage = {
    perPageText: "lorem ppsum",
    nextButtonText: "labore nostrud",
    /* more ... */
};
languageServiceProvider.setLang("lorem", loremIpsumLanguage)

/**
 * @function setLang
 * @param {String} lang           the name of the language
 * @param {Object} translations   an object with the translated text
*/

You can also change any default text for an existing language and that will reflect the changes globally. For example:

// the default text for the download button in the export component is "export as"
// we may want change that to "download as"
languageServiceProvider.setLangText("en", "downloadText", "download as:")

/**
 * @function setLangText
 * @param lang
 * @param {String} key     the key in the lang object
 * @param {String} text    the text will be display to the user
*/

Custom order of components

VueDataTable uses CSS's grid display to specify the position of its components (search filter, pagination, entries info, per page options, download button).

We can specify the position of the components by including our custom CSS/SCSS and overriding the defaults.

By default, this is how VueDataTable displays the components:

.data-table {
    display: grid;
    width: 100%;
    grid-template-columns: 25% 25% 25% 25%;
    &> div {
        margin-top: 1rem;
        max-width: 100%;
    }
    & > .data-table-search-filter, .data-table-pagination, .data-table-export-data {
        margin-left: auto
    }
    @media (min-width: 1401px) {
        grid-template-areas:
            "perPage search search search"
            "table table table table"
            "info pagination pagination download";
    }
    @media (min-width: 1051px) AND (max-width: 1400px) {
        grid-template-areas:
            "perPage search search search"
            "table table table table"
            "info pagination pagination pagination"
            ". . download download";
    }
    @media (min-width: 851px) AND (max-width: 1050px) {
        grid-template-areas:
            "perPage search search search"
            "table table table table"
            "pagination pagination pagination pagination"
            "info info download download";
    }
    @media (max-width: 800px) {
        & > .data-table-pagination {
            flex-wrap: wrap;
        }
    }
    @media (min-width: 651px) AND (max-width: 850px) {
        grid-template-areas:
            "perPage search search search"
            "table table table table"
            "pagination pagination pagination pagination"
            "info info info info"
            "download download download download";
    }
    @media (max-width: 650px) {
        grid-template-areas:
            "search search search search"
            "perPage perPage perPage perPage "
            "table table table table"
            "pagination pagination pagination pagination"
            "info info info info"
            "download download download download";
        & > .data-table-per-page {
            margin-left: auto
        }
    }
}

Feel free to copy the styles above, modify it, and then set the position of the components as you want.

Custom Components

Besides a custom component for each column, you provide custom components for the table's footer, the column's sorting icon (the icon displayed if the columns is sorted), and the column's sorting index (the index of the current column if it is being sorted and multi column sorting is enabled).

Footer

The property footerComponent sets the component to render the table's footer. The component can be either the component Object, or a String equals to the name of the registered component.

The footerComponent must be a <tfoot> HTML element and it must have the properties data, dataDisplayed, dataFiltered. If the component does not specify those properties in props, Vue will probably think they are some custom HTML attribute and their values will be show as HTML attributes, which is really messy.

The property data correspond to all data passed to VueDataTable. The dataDisplayed corresponds to all data that is currently visible on the table. The dataFiltered corresponds to all data that was filtered by a search query. These properties can be used to perform common operations such as calculating the sum of the values of the total rows of a certain column.

Example

Suppose we have a table that of fruits. The data is an array of objects whose properties are name, price, and amount. We can provide a custom footer to show the total amount of fruits bought and the total price.

The footer component would be something like:

<template>
  <tfoot v-show="dataDisplayed.length > 0">
    <td>Total</td>
    <td></td> 
    <td>{{ totalAmount }}</td> 
    <td>{{ totalPrice }}</td>
  </tfoot>  
</template>
<script>
export default {
  name: "TableFooter",
  computed: {
    totalPrice() {
      let s = 0;
      for (let f of this.dataDisplayed)
        s += f.price * f.amount;
      return s;
    }, 
    totalAmount() {
      let s = 0;
      for (let f of this.dataDisplayed)
        s += f.amount;
      return s;
    }
  },
  props: {
    data: Array,
    dataDisplayed: Array,
    dataFiltered: Array,
  }
}
</script>

And we pass this component as follow:

<template>
	<data-table v-bind="tableProps"/>
</template>
<script>
import TableFooter from './TableFooter.vue'

export default {
	/* ... some code */
	data() {
		return {
			tableProps: {
				columns: [ /* ... code */ ],
				data: [ /* ... more code */ ],
				footerComponent: TableFooter,
			}
		}
	}
}
</script>

Alternately, you can register the component and pass a string:

/* earlier on */
import TableFooter from './TableFooter.vue'
Vue.component("table-footer", TableFooter)

/* later on */
	footerComponent: "table-flooter"

Sorting icon

By default, VueDataTable will display arrows to indicate the sorting direction when sorting a column. The SortingIcon component is wrapped in a th element. The th element has a data-sorting attribute that may be asc or desc only. Based on this value, we display an arrow_up or an arrow_down icon using CSS rules.

<template>
    <span class="data-table-sorting-icon">&nbsp;</span>
</template>
<style lang="scss" scoped>
.data-table-sorting-icon {
    &::after {
        content: "\2193";
    }
    &::before {
        content: "\2191";
    }
    &::after, &::before {
        opacity: 0.5;
    }
    [data-sorting="asc"] &::before, [data-sorting="desc"] &::after {
        opacity: 1;
    }
}
</style>

Note: Some code was omitted to keep it clean.

If we want to add our custom icons for this, then we can register our component.

import SortingIcon from "./path/to/SortIcon.vue";

export default {
    computed: {
        bindings() {
            return {
                SortingIconComponent: SortingIcon,
                data: [],
                /**/
            };
        }
    }
}

Sorting Index Icon

When sorting multiple columns, VueDataTable will display an icon with a index indicating which column has the priority in the sorting process.

<template>
    <span class="data-table-sort-index">
        {{ index }}
    </span>
</template>

If we want to add our own component for this, we can register it just like we did before.

import SortingIndex from "./path/to/SortingIndex.vue";

export default {
    computed: {
        bindings() {
            return {
                SortingIndexComponent: SortingIndex,
                data: [],
                /**/
            };
        }
    }
};

In our SortingIndex component, we must have a index property, which correspondent to the index of the column in the sorting process.

export default {
    name: "SortingIndex",
    props: {
        index: {
            type: Number,
            required: true
        }
    }
};

License

MIT

Versioning

This project uses SemVer.

Contributing

Pull requests are very welcome.