0

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:

  1. Parses each cell into a list
  2. Tries to match the items in the list of point #1 to the selected tags in the column's searchList.
  3. 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 Tag selection - default

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

Step 3: with Tag A selected, the item with tags A B and C does not appear Tag selection - Tag A selected, 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.

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.