# vue3-easy-table

> A simple and highly customizable component for creating data tables based on plugins.

Latest version **1.4.1** (published 2021-07-21) · MIT license · 0 weekly downloads

## Install

```sh
npm install vue3-easy-table
pnpm add vue3-easy-table
yarn add vue3-easy-table
bun add vue3-easy-table
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.4.1 |
| Published | 2021-07-21 |
| First published | 2021-06-18 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 3 |
| Unpacked size | 2.4 MB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Chrisitan Albán |
| Maintainers | chrisalban |
| Keywords | vue3, vue 3, table, vue3 table, data table, easy table, easy-table |

## Links

- npm: https://www.npmjs.com/package/vue3-easy-table
- Repository: https://gitlab.com/chrisalban/vue3-easy-table
- Homepage: https://gitlab.com/chrisalban/vue3-easy-table/-/tree/master
- Issues: https://gitlab.com/chrisalban/vue3-easy-table/issues
- npm.io page: https://npm.io/package/vue3-easy-table

## Dependencies (3)

- [vue](https://npm.io/package/vue.md) ^3.0.0
- [core-js](https://npm.io/package/core-js.md) ^3.6.5
- [vue-class-component](https://npm.io/package/vue-class-component.md) ^8.0.0-0

## Alternatives

- [@lexical/table](https://npm.io/package/@lexical/table.md) — 3.0M weekly downloads
- [mantine-datatable](https://npm.io/package/mantine-datatable.md) — 98.2K weekly downloads
- [react-native-collapsible-tab-view](https://npm.io/package/react-native-collapsible-tab-view.md) — 70.6K weekly downloads
- [@handsontable/vue3](https://npm.io/package/@handsontable/vue3.md) — 16.1K weekly downloads
- [vuewordcloud](https://npm.io/package/vuewordcloud.md) — 7.2K weekly downloads

## Recent versions

- 1.4.1 (latest) — 2021-07-21
- 1.4.0 — 2021-07-21
- 1.3.0 — 2021-06-24
- 1.1.2 — 2021-06-24
- 1.1.1 — 2021-06-18
- 1.0.0 — 2021-06-18

## README

# Vue 3 Easy Table

A simple and highly customizable component for creating data tables based on plugins.

![preview](https://gitlab.com/chrisalban/vue3-easy-table/-/raw/master/preview.png)

[View demo](https://codesandbox.io/s/sad-fermat-4vwm9)

## Table of Contents
* [Installation](#installation)
  * [NPM](#npm)
* [Usage](#usage)
  * [Register globally](#register-globally)
    * [Basic example](#basic-example)
    * [Advanced example](#advanced-example)
  * [Configuring the components](#configuring-the-components)
    * [Data Table](#data-table)
      * [Data Table Props](#data-table-props)
      * [Data Table Events](#data-table-events)
      * [Data Table Slots](#data-table-slots)
      * [Data Table Theming](#data-table-theming)
    * [Keyword Filter](#keyword-filter)
      * [Keyword Filter Props](#keyword-filter-props)
      * [Keyword Filter Theming](#keyword-filter-theming)
    * [Sort Filter](#sort-filter)
      * [Sort Filter Props](#sort-filter-props)
      * [Sort Filter Theming](#sort-filter-theming)
    * [Paginator](#paginator)
      * [Paginator Props](#paginator-props)
      * [Paginator Slots](#paginator-slots)
      * [Paginator Theming](#paginator-theming)
    * [Totalizer](#totalizer)
      * [Totalizer Props](#totalizer-props)
      * [Totalizer Theming](#totalizer-theming)
    * [Page Number](#page-number)
      * [Page Number Props](#page-number-props)
      * [Page Number Theming](#page-number-theming)

## Installation

### NPM

```bash
npm install vue3-easy-table --save
```

## Usage

### Register globally

First, register the full components in your app entry point (`app.js`) .

```typescript
import { createApp} from 'vue'
import App from './App.vue'
import EasyTable from 'vue3-easy.table'
// Import de default theme, or you can create your own custom theme
import 'vue3-easy-table/themes/default.css'
...
createApp(App)
    .use(EasyTable)
    .mount('#app')
```

Or also you can register components individually.

```tsx
import { createApp} from 'vue'
import App from './App.vue'
import {
    useEasyDataTable,
    useEasyPaginator,
    useEasySortFilter,
    useEasyTotalizer
} from 'vue3-easy.table'
// Import de default theme, or you can create your own custom theme
import 'vue3-easy-table/themes/default.css'
...
createApp(App)
    .use(useEasyDataTable)
    .use(useEasyPaginator)
    .use(useEasySortFilter)
    .use(useEasyTotalizer)
    .mount('#app')
```

Next, use it on your template

#### Basic Example

```vue
<template>
	<div class="overflow-x-auto w-full">
        <e-data-table
          :headers="headers"
          :items="items"
          :is-loading="loading">
        </e-data-table>
	</div>
</template>
<script>
export default {
    data() {
        return {
            headers: [
                { label: 'Id', key: 'id'},
                { label: 'Username', key: 'username'},
                { label: 'Full Name', key: 'fullName'},
                { label: 'Amount', key: 'amount', formatter: (value) => `$${value}` },
            ],
            items: [
                { id: 1, username: 'Octavius Rex', fullName: 'Octavius Rex', amount: 1000 },
                { id: 2, username: 'spongebob', fullName: 'Sponge Bob Squarepants', amount: 1500 },
                { id: 3, username: 'patrickstar', fullName: 'Patrick Star', amount: 1020 },
                { id: 4, username: 'sandycheeks', fullName: 'Sandy Cheeks', amount: 800 },
                { id: 5, username: 'eugenekrabs', fullName: 'Eugene H. Krabs', amount: 950 },
                { id: 6, username: 'sheldonplankton', fullName: 'Sheldon J. Plankton', amount: 300 },
            ],
            isLoading: false
        }
    }
}
</script>

<style>
</style>
```

#### Advanced Example

```vue
<template>
    <div>
        <e-keyword-filter v-model:filtered="filtered" :original="items"></e-keyword-filter>
        <e-data-table
            :headers="headers"
            :items="filtered"
            :is-loading="isLoading"
            :current-page="currentPage"
            v-model:total-items="totalItems"
            :per-page="perPage"
            rowStyle="link"
            @row-click="showUser">

            <template v-slot:header[default]="{ header }">
                {{ header.label }}
                <e-sort-filter :key-param="header.key" v-model:sort-by="sortBy" v-model:sort-desc="sortDesc" v-model:filtered="filtered"/>
            </template>
            <template v-slot:cell[username]="{ cell }">
                <div class="flex items-center">
                    <span>{{ `${cell.item.username}` }}</span>
                </div> 
            </template>
            <template v-slot:footer[amount]="{ footer }">
                <e-totalizer :key-column="footer.key" :items="filtered" :formatter="footer.formatter"/>
            </template>
        </e-data-table>
        <div class="mt-auto">
            <e-paginator v-model:current-page="currentPage" v-model:total-items="totalItems" v-model:per-page="perPage" />
        </div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            headers: [
                { label: 'Id', key: 'id'},
                { label: 'Username', key: 'username'},
                { label: 'Full Name', key: 'fullName'},
                { label: 'Amount', key: 'amount', formatter: (value) => `$${value}` },
            ],
            items: [
                { id: 1, username: 'Octavius Rex', fullName: 'Octavius Rex', amount: 1000 },
                { id: 2, username: 'spongebob', fullName: 'Sponge Bob Squarepants', amount: 1500 },
                { id: 3, username: 'patrickstar', fullName: 'Patrick Star', amount: 1020 },
                { id: 4, username: 'sandycheeks', fullName: 'Sandy Cheeks', amount: 800 },
                { id: 5, username: 'eugenekrabs', fullName: 'Eugene H. Krabs', amount: 950 },
                { id: 6, username: 'sheldonplankton', fullName: 'Sheldon J. Plankton', amount: 300 },
            ],
            filtered: [],
            isLoading: false,
            perPage: 3,
            totalItems: 0,
            currentPage: 1,
            sortBy: 'username',
            sortDesc: false,
        }
    },
    methods: {
        showUser(user) {
            alert(user.fullName)
        }
    }
}
</script>

<style>
</style>
```

### Translation

This feature is still under development and there are still translations to be made, you can configure the language that will be displayed by certain components, to use the component translation you must import the translation file and configure it in the entry point of your application..

```javascript
import { createApp } from 'vue'
import App from './App.vue'
import EasyTable from 'vue3-easy.table'
// Import de default theme, or you can create your own custom theme
import 'vue3-easy-table/themes/default.css'
import es from 'vue3-easy-table/src/lang/es'

changeLang(es)
...
createApp(App)
    .use(EasyTable)
    .mount('#app')
```

### Configuring the components

Vue3 Easy Table includes components that offer a large number of properties for your configuration.

#### Data Table

The data table is the main component that displays a table with the data that it receives by parameter.

##### Data Table Props

###### *headers*

Sets an object that allows you to configure the table headers.

*type:*`Array`

*required:*`true`

```javascript
/*
* You can configure each header individually.
* label: The label to be displayed in the column header
* username: The name of the item's parameter
* formatter: Optionally you can include a function that formats the value that is passed to the cell
* width: Optinally you can indicate the width of the column on a string, ex: '20%', '50px', '2.5rem'
* aligment: Optionally you can indicate de column aligment on a string, ex: 'left', 'center', 'right'
*/
[
    { label: 'Id', key: 'id', width: '20px'},
    { label: 'Userbaname', key: 'username'},
    { label: 'Full Name', key: 'fullName'},
    { label: 'Amount', key: 'amount', formatter: (value) => `$${value}`, aligment: 'right' },
]

```

###### *row-style*

Specify a function that returns a string with the name of the class to apply depending on what is evaluated within the function, the item of the row is passed as the first parameter of the function.

*type:* `Function`

*default:* `(item) => ''`

```javascript
const rowStyle = (item) => item.isDeleted ? 'item-deleted-class' : ''
```

###### *items*

It is the collection of data that wjjkill be iterated in the table.

*type:* `Array`

*required:* `true`

```javascript
[
    { id: 1, username: 'Octavius Rex', fullName: 'Octavius Rex', amount: 1000 },
    { id: 2, username: 'spongebob', fullName: 'Sponge Bob Squarepants', amount: 1500 },
    { id: 3, username: 'patrickstar', fullName: 'Patrick Star', amount: 1020 },
    { id: 4, username: 'sandycheeks', fullName: 'Sandy Cheeks', amount: 800 },
    { id: 5, username: 'eugenekrabs', fullName: 'Eugene H. Krabs', amount: 950 },
    { id: 6, username: 'sheldonplankton', fullName: 'Sheldon J. Plankton', amount: 300 },
]
```

###### *is-loading*

Allows you to specify if the table is in loading state or not.

*type:* `Boolean`

*default:* `false`

```javascript
isLoading: true
```

###### *current-page*

Indicates the current page number where the pagination is located.

*type:* `Number`

*default:* `1`

```javascript
currentPage: 5 // Show de items in the page 5
```

###### *per-page*

Indicates the number of pages to be displayed in the table.

*type:* `Number`

*default*: `15`

```javascript
perPage: 15
```
###### *empty-label*

The text that will appear in the table when it is empty and there is no slot already applied.

*type*: `String`

*default*: `Empty`

```javascript
emptyLabel: 'Empty Table'
```

##### Data Table Events

`@row-clicked`

The event is fired when a row is clicked.

##### Data Table Slots

You can customize the content within the headers, cells, feet, through the slots.

To refer to a specific slot you can use the syntax:

```vue
v-slot:header[headerKey]
v-slot:cell[headerKey]
v-slot:footer[headerKey]
```

Without wanting to set a slot for everyone you can use the default slot that will be mounted by default

```vue
v-slot:header[default]
v-slot:cell[default]
v-slot:footer[default]
```
You can customize the message that appears when the table is empty with the slot `v-slot:cell[empty]`.

```vue
v-slot:cell[default]
```

```vue
<!-- Header template -->
<template v-slot:header[default]="{ header }">
	{{ header.label }}
	<e-sort-filter :key-param="header.key" v-model:sort-by="sortBy" v-model:sort-desc="sortDesc" v-model:items="items"/>
</template>
<!-- Cell template -->
<template v-slot:cell[username]="{ cell }">
	<div class="flex items-center">
        <span>{{ `${cell.item.username}` }}</span>
    </div> 
</template>
<!-- Emtpy template -->
<template v-slot:cell[empty]>
	<div class="flex items-center">
        <span>Empty table</span>
    </div> 
</template>
<!-- Footer template -->
<template v-slot:footer[amount]="{ footer }">
	<e-totalizer :key-column="footer.key" :items="items" :formatter="footer.formatter"/>
</template>
```

##### Data Table Theming

You can fully customize the plugin with the classes it includes.

```css
.et-container {
    width: 100%;
    border-style: solid;
    border-width: 1px;
    border-radius: .8rem;
    border-color: #191919;
    overflow: hidden;
}

.et-container .et-table {
    position: relative;
    width: 100%;
    border-collapse: collapse;
}

.et-container .et-table.loading {
    opacity: 50%;
}

.et-container .et-table-header {
    position: sticky;
    top: 0;
    background-color: #e4e3e5; 
}

.et-container .et-table-header-container {
    display: flex;
    padding: 0.2rem 1rem;
    height: 100%;
    justify-content: center;
    align-items: center;
    padding: .2rem 2rem;
}

.et-container .et-table-cell {
    font-size: 1rem;
    text-align: center;
}

.et-container .et-table-body-row.et-table-row-link {
    cursor: pointer;
}

.et-container .et-table-body-row.et-table-row-link:hover {
    background-color: #b5b5b5;
    box-shadow: 0 0 0 0 #333333;
    transition: all .3s ease;
}

.et-container .et-table-cell-container {
    display: flex;
    padding: 1rem 2rem;
}
```

#### Keyword Filter

Plugin that allows you to filter the items by a keyword.

##### Keyword Filter Props

###### *filtered*

It must be an empty array that the filter will use as temporary, keep in mind that the collection is not modified instead a copy of the original collection is created.

*type:* `Array`

*required:* `true`

```javascript
filtered: []
```

###### *original*

It is the original collection to which the filter is applied.

*type:* `Array`

*required:* `true`

```javascript
[
    { id: 1, username: 'Octavius Rex', fullName: 'Octavius Rex', amount: 1000 },
    { id: 2, username: 'spongebob', fullName: 'Sponge Bob Squarepants', amount: 1500 },
    { id: 3, username: 'patrickstar', fullName: 'Patrick Star', amount: 1020 },
]
```
###### *placeholder*

The text to display in the placeholder.

*type:* `String`

*default:* `Search`

```javascript
placeholder: 'Search item'
```
##### Keyword Filter Theming

You can fully customize the plugin with the classes it includes.

```css
.et-keyword {
    padding: .5rem;
}

.et-keyword .et-keyword-input
{
    padding: .5rem;
    border-radius: .5rem;
    border: none;
}
```

#### Sort Filter

Plugin that allows you to sort the items within the array by a given key in ascending or descending order.

##### Sort Filter Props

###### *filtered*

Collection of data that the filter will sort, keep in mind that the filter will modify the original collection.

*type:* `Array`

*required:* `true`

```javascript
[
    { id: 1, username: 'Octavius Rex', fullName: 'Octavius Rex', amount: 1000 },
    { id: 2, username: 'spongebob', fullName: 'Sponge Bob Squarepants', amount: 1500 },
    { id: 3, username: 'patrickstar', fullName: 'Patrick Star', amount: 1020 },
]
```
###### *header*

The column header, the filter will look for the meta.isSortable parameter to verify if the column can apply the filter or not, to deactivate the filter in a specific column the value must be false.

*type:* `Object`

*required:* `false`

```javascript
/* In the headers object */
[
    { label: 'Id', key: 'id', width: '20px', meta: { isSortable: false }},
    ...
]
```
###### *key-param*

The key of the current column on which the plugin will act.

*type:* `String`

*required:* `true`

```javascript
keyParam: 'username'
```
###### *sort*-by

The key of the column by which the plugin should sort.

*type:* `String`

*required:* `true`

```javascript
sortBy: 'username'
```
###### *sort-desc*

Direction in which the items should be ordered.

*type:* `Boolean`

*required:* `true`

```javascript
sortDesc: true
```
##### Sort Filter Slots

You can customize the content of the component such as the ordering buttons in ascending, descending order or when the filter is not applied in that column.

```vue
v-slot:neutral-button
v-slot:desc-button
v-slot:desc-button
```

```vue
<!-- Neutral Button template -->
<template #neutral-button>
	<fa-icon icon="sort"/>
</template>
<!-- Desc Button template -->
<template #desc-button>
	<fa-icon icon="sort-down"/>
</template>
<!-- Asc Button template -->
<template #asc-button>
	<fa-icon icon="sort-up"/>
</template>
```
##### Sort Filter Theming

You can fully customize the plugin with the classes it includes.

```css
.et-sorter
{
    display: flex;
    justify-content: center;
    margin-left: 1rem;
    margin: 0.2rem 1rem;
    border-radius: .3rem;
    transition: all .3s ease;
    border: none;
    padding: .2rem .5rem;
}

.et-sorter:hover,
.et-sorter:active
{
    background-color: #b5b5b5;
}

.et-sorter.neutral
{
    width: 100%;
    color: #333333;
}
```

#### Paginator

Plugin that allows you to control the pagination of a table.

##### Paginator Props

###### *current-page*

Indicates the current page that the component should show as marked.

*type:* `Number`

*default:* `1`

```javascript
currentPage: 1
```
###### *total-items*

The total number of items in the data collection, this data is used so that the plugin can calculate the number of pages.

*type:* `Number`

*required:* `true`

```javascript
totalItems: 150
```
###### *per-page*

The number of items displayed per page, the plugin uses this data to calculate the number of pages.

*type:* `Number`

*required:* `true`

```javascript
perPage: 15
```
###### *offset*

The maximum number of pages to be displayed.

*type:* `Boolean`

*default:* `5`

```javascript
offset: 5
```
##### Paginator Slots

You can customize the paging content such as the forward, backward or go to the page buttons through the slots that it includes. 

```vue
v-slot:prev
v-slot:page
v-slot:next
```

```vue
<!-- Prev Button template -->
<template #prev>
	<fa-icon icon="angle-left"/>
</template>
<!-- Page Button template -->
<template #page="{ page }">
	<span>{{ page }}</span>
</template>
<!-- Next Button template -->
<template #next>
	<fa-icon icon="angle-right"/>
</template>
```
##### Paginator Theming

You can fully customize the plugin with the classes it includes.

```css
.et-paginator
{
    display: flex;
    flex-direction: row-reverse;
}

.et-paginator .et-paginator-container
{
    display: flex;
    margin: 1rem auto;
    border-width: 1px;
    border-style: solid;
    border-color:#333333; 
    border-radius: .3rem;
    overflow: hidden;
}

.et-paginator .nav-button
{
    padding: .2rem 1rem;
    border-right: 1px solid #333333;
    outline: none;
    background-color: transparent;
}

.et-paginator .nav-button.pre
{
    padding: .2rme 1rem;
    border-right: 1px solid #333333;
    outline: none
}

.et-paginator .nav-button.next
 {
     border: none;
}

.et-paginator .nav-button:hover {
    background-color: #b5b5b5;
}

 .et-paginator .nav-button.active {
    background-color: #05308c;
    color: white;
    border: 1px solid #05308c;
}
```
#### Totalizer

Complement that calculates the total, of a column, keep in mind that if there are other filters applied, all the filtered items will be added.

##### Totalizer Props

###### *key-column*

The key of the column to be totaled.

*type:* `String`

*required:* `true`

```javascript
keyColumn: 'amount'
```
###### *items*

The filtered data collection.

*type:* `Array`

*required:* `true`

```javascript
[
    { id: 1, username: 'Octavius Rex', fullName: 'Octavius Rex', amount: 1000 },
    { id: 2, username: 'spongebob', fullName: 'Sponge Bob Squarepants', amount: 1500 },
    { id: 3, username: 'patrickstar', fullName: 'Patrick Star', amount: 1020 },
]
```
###### *formatter*

The formatting function that will be applied to the footer.

*type:* `Function`

*required:* `false`

```javascript
formatter: (value) => value.toLowerCase()
```

##### Totalizer Theming

You can fully customize the plugin with the classes it includes.

```css
.et-totalizer {
    font-weight: bold;
    text-align: center;
}
```

#### Page Number

Add-in that displays table information such as total number of records, current page, and number of pages in the table..

##### Page Number Props
###### *current-page*

Indicates the current page that the component should show.

*type:* `Number`

*default:* `1`

```javascript
currentPage: 1
```

###### *total-items*

The total number of items in the data collection, this data is used so that the plugin can calculate the number of pages.

*type:* `Number`

*required:* `true`

```javascript
totalItems: 150
```
###### *per-page*

The number of items displayed per page, the plugin uses this data to calculate the number of pages.

*type:* `Number`

*required:* `true`

```javascript
perPage: 15
```

##### Page Number Theming

You can fully customize the plugin with the classes it includes.

```css
.et-page-number { /* Wrapper */ }
.et-totalizer .et-total-items { /* Label that show de total items */ }
.et-totalizer .et-pipe-separator { /* Separator caracter */ }
.et-totalizer .et-current-page { /* Label that show de current page */ }
.et-totalizer .et-page-separator { /* Separator page normally "of" */ }
.et-totalizer .et-total-pages { /* Label that show de total pages */ }
```

---
_Source: https://npm.io/package/vue3-easy-table · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
