
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
vue-displaytable
Advanced tools
A highly customizable and modular Table component library for Vue 3, built with TypeScript and Tailwind CSS 4
A table component for Vue 3 designed with a modular structure for high customization and editing
sortable.npm install vue-displaytable
Import the TableMain component and its types TableColumn, TableData into your .vue file. Then fill the TableColumn array with the name of columns, and TableData array with objects that have key-value pairs corresponding to the TableColumn key values. An example of the basic usage is as follows:
<script setup lang="ts">
import { TableMain } from 'vue-displaytable';
import type { TableColumn, TableData } from 'vue-displaytable';
const columns: TableColumn[] = [
{ key: 'id', label: 'ID', width: '10%', sortable: true },
{ key: 'name', label: 'Name', width: '30%' },
{ key: 'email', label: 'Email', width: '40%' },
{ key: 'role', label: 'Role', width: '20%' sortable: false },
];
const data: TableData[] = [
{ id: 1, name: 'John Doe', email: 'john@example.com', role: 'Admin' },
{ id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'User' },
];
</script>
<template>
<TableMain :columns="columns" :data="data" />
</template>

You can also populate the table dynamically using API responses. You have to make use of Vue's reactivity features to initialize a reactive array of TableData and then fill the array with the values you get from your API. Make sure the columns' keys in TableColumn array are same as the attributes you'd receive from your API!
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { TableMain } from 'vue-displaytable';
import type { TableColumn, TableData } from 'vue-displaytable';
const columns: TableColumn[] = [
{ key: 'id', label: 'ID', width: '10%', sortable: true },
{ key: 'name', label: 'Name', width: '30%', sortable: true },
{ key: 'email', label: 'Email', width: '40%' },
{ key: 'company', label: 'Company', width: '20%', sortable: true },
];
const users = ref<TableData[]>([]);
const loading = ref(true);
onMounted(async () => {
try {
const response = await fetch(
'https://jsonplaceholder.typicode.com/users'
);
const data = await response.json();
users.value = data.map((user: any) => ({
id: user.id,
name: user.name,
email: user.email,
company: user.company.name,
}));
} finally {
loading.value = false;
}
});
</script>
<template>
<div v-if="loading">Loading...</div>
<TableMain v-else :columns="columns" :data="users" />
</template>

You can insert your own logic into the code by using slots (such as clickable cells that open a link, or an action button group of edit and delete buttons).
For this you have to define a new column with a key. Then inside <TableMain></TableMain> tags, create a <template #cell-columnkey="{args}"></template>
template tag, that refers to the key of the column. Inside the template tag, you can pass your own code, which be rendered using slots
Example usage:
<script setup lang="ts">
import TableMain from '../components/Table/components/TableMain.vue';
import type { TableColumn, TableData } from '../components/Table';
const actionSlotCols: TableColumn[] = [
{ key: 'id', label: 'EAN', sortable: true, width: '20%' },
{ key: 'name', label: 'Product Name', sortable: true, width: '40%' },
{ key: 'actions', label: 'Actions', sortable: false, width: '50%'}
];
const actionSlotData: TableData[] = [
{ id: 48234, name: 'Amazing Tool' },
{ id: 39534, name: 'Horrible Tool' },
];
</script>
<template>
<TableMain :columns="actionSlotCols" :data="actionSlotData">
<template #cell-id="{value}"> <!-- Clickable Link in the 'id' column -->
<a :href="`${value}`" class="text-blue-500">
{{value}}
</a>
</template>
<template #cell-actions> <!-- Action Button Group in the 'actions' column -->
<div class="flex gap-1">
<button class="px-1 py-1 bg-blue-500 text-black rounded text-sm">
Edit
</button>
<button class="px-1 py-1 bg-red-500 text-black rounded text-sm">
Delete
</button>
</div>
</template>
</TableMain>
</template>

| Prop | Type | Required | Description |
|---|---|---|---|
columns | TableColumn[] | Yes | Array of column definitions |
data | TableData[] | Yes | Array of row data objects |
interface TableColumn {
key: string; // Unique identifier, matches data property
label: string; // Display text for header
sortable?: boolean; // Enable sorting
width?: string; // Column width (it converts into a CSS style, e.g., '20%', '100px')
}
interface TableData {
[key: string]: any; // Flexible key-value pairs
}
Vue-DisplayTable is designed completely modularly. Each part can be imported individually and used to your liking:
import {
TableMain, // Main wrapper component
TableHeader, // Table header (thead)
TableHeaderCell, // Individual header cell (th)
TableBody, // Table body (tbody)
TableRow, // Individual row (tr)
TableCell, // Individual cell (td)
} from 'vue-displaytable';
Vue-DisplayTable uses Tailwind CSS classes, albeit very minimal to not have any conflicting styles with your individual ones. To use the default styles, make sure that you have Tailwind 4 installed, otherwise the table may seem off.
You can override styles using Tailwind's utility classes or your own CSS. The components use standard HTML table elements (table, thead, tbody, tr, th, td).
I've taken a huge inspiration by https://github.com/DataTables/DataTablesSrc while creating this library. At work I initially used DataTables for a project, after which I decided to make my own library to meet my project's individual needs. As I noticed that my own library strays far away from DataTables' design and principle (mainly the jQuery and Tailwind approach, Vue's reactivity approach compared to jQuery and some customization concerns I experienced), I've decided to open-source the code I've written.
MIT © fx-ntm
FAQs
A highly customizable and modular Table component library for Vue 3, built with TypeScript and Tailwind CSS 4
We found that vue-displaytable demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.