I am trying to create a Vue DataTable component so I can make several tables without having to worry about their overall set-up (since it will be done in this main table component).
One of the features I want is for the columns that use searchList
(similar to the MultiSelect column in Notion) to recognize cells that have a list of values (here described as “tags”). I need the search function to recognize that, if the cell content is a list, then each individual item in that list may be searched and accounted for when it comes to filtering.
For that, I believe I need to modify the columns.search
API so that, for each column it applies to, it:
- Parses each cell into a list
- Tries to match the items in the list of point #1 to the selected tags in the column’s searchList.
- Returns true if a single item matches
However, I am using Vue and not the “default” DataTables; and I am using Vue as a child component, not as the parent one. The reference documentation says I need to use the dt()
method to access the API that should allow me to modify columns.search()
. I have seen the example of how to do so for a predefined column with a predefined search query (here, with numbers), but I am stuck on how to do so for a general case scenario (again, the Vue component is meant as a template for any table I may want to add).
How do I obtain the searchlist selected items when I don’t know what information each column will contain yet? How do I do the same for each cell?
So far, I’ve managed to parse each item for display, but not for filtering.
Sample code and result below
Step 1: Display with no filtering yet

Step 2: Display with Tag A selected (Tag A Tag B and Tag C count as a single value to searchList – Not intended)

Step 3: with Tag A selected, the item with tags A B and C does not appear

Code on main.js
:
import './assets/css/main.css'
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import '@fortawesome/fontawesome-free/js/all'
const app = createApp(App)
app.use(router)
app.mount('#app')
Code on App.vue
:
<script setup>
import { RouterView } from 'vue-router'
import Sidebar from './components/sidebar/Sidebar.vue';
import {sidebarWidth} from './components/sidebar/sidebar-state.js';
</script>
<template>
<Sidebar />
<div :style="{'margin-left': sidebarWidth}">
<RouterView />
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
</style>
Code on Table.vue
:
<script setup>
import jquery from 'jquery';
import DataTable from 'datatables.net-vue3';
import DataTablesLib from 'datatables.net-dt';
import 'datatables.net-colreorder-dt';
import 'datatables.net-columncontrol-dt';
import 'datatables.net-fixedheader-dt';
import 'datatables.net-fixedcolumns-dt';
import 'datatables.net-responsive-dt';
import 'datatables.net-searchpanes-dt';
DataTable.use(DataTablesLib);
const props = defineProps({
columns: {
default: [
{data: 'id', title: 'PersonId',},
{data: 'name', title: 'PersonName',},
]
},
options: {
default: {
responsive: true,
scrollX: true,
fixedHeader: true,
fixedColums: true,
colReorder: true,
paging: false,
scrollY: 300,
scrollCollapse: true,
columnControl: ['order', ['searchList']],
ordering: {
indicators: false
}
}
},
data: {
default: [
{name:'RowItem1ValueA', id:'RowItem1ValueB'},
{name:'RowItem2ValueA', id:'RowItem2ValueB'},
]
}
})
</script>
<template>
<DataTable :columns="props.columns" :options="props.options" :data="props.data"
class="display compact">
</DataTable>
</template>
<style>
@import 'datatables.net-dt';
@import 'datatables.net-responsive-dt';
@import 'datatables.net-fixedheader-dt';
@import 'datatables.net-fixedcolumns-dt';
@import 'datatables.net-colreorder-dt';
@import 'datatables.net-columncontrol-dt';
@import 'datatables.net-searchpanes-dt';
</style>
<style scoped>
th, td { white-space: nowrap; }
td.multiples{
white-space: pre-wrap;
}
div.dataTables_wrapper {
margin: 0 auto;
}
div.container {
width: 80%;
}
</style>
Code on OrganizationView.vue
(view where I’m trying to use the default table as a template for “random” data):
<script setup>
import Table from '../components/table/Table.vue'
const tableInfoPeople = {
'Columns': [
{data: 'dtPerson', title: 'Person',},
{
data: 'dtTags',
title: 'MultiTags',
render: {
_: '[, ].id',
sp: '[].id'
}
},
],
'Data': [
{ dtPerson: 'Name01',
dtTags: [
{'id': 'TagA'}
],
},
{ dtPerson: 'Name02',
dtTags: [
{'id': 'TagA'}, {'id': 'TagB'}, {'id': 'TagC'}
],
},
{
dtPerson: 'Name03',
dtTags: [{'id': 'TagD'}],
},
]
}
</script>
<template>
<Table :columns="tableInfoPeople.Columns" :data="tableInfoPeople.Data">
</Table>
</template>
I appreciate any help you might give me.
Note: I know the css doesn’t look great, I wanted to change it after fixing the functionality.