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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.