How to add a custom search/filter function for DataTables' searchList using Vue templates?

How to add a custom search/filter function for DataTables' searchList using Vue templates?

ChadChaddingtonChadChaddington Posts: 2Questions: 1Answers: 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](https://datatables.net/reference/content/searchList "searchList") 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](https://datatables.net/reference/api/columns().search() "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

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.

This question has an accepted answers - jump to answer

Answers

  • allanallan Posts: 65,071Questions: 1Answers: 10,775 Site admin

    Regardless of whether it is Vue or native JS, there isn't an option for that in ColumnControl at the moment. There would need to be changes in the source to support arrays. I'd actually suggest creating a new searchListArray content type rather than trying to modify searchList for it.

    A pull request with this addition would be welcome.

    Allan

  • ChadChaddingtonChadChaddington Posts: 2Questions: 1Answers: 0
    edited 11:40AM

    Thank you for your prompt answer, @allan!

    I have 2 follow-up topics (I am newer to datatables than I'd like, so forgive me if I'm referring to some components in an inaccurate way):

    1. New Content Type:

      • If there isn't an option for list support in the source ColumnControl, then - is it possible to create a new content type using "only" the API?
      • If not, how does one go about creating one in the source ColumnControl code? Is there documentation for adding new content types?
    2. Modifying the base search API:

      • The seachList content type is based on the search API right?
      • If so, is it viable to modify the search API instead so there's a match for every item in a cell's list - therefore ensuring the searchList content type consequently recognizes every item in a cell's list? Is registering a new data type as per the types section a valid way to do it, or would this only work for display/formatting purposes?
  • allanallan Posts: 65,071Questions: 1Answers: 10,775 Site admin
    Answer ✓

    Your easiest option will be to clone the ColumnControl repo and look at how the content types are currently written. The one of most interest will be the searchList code.

    Specifically, have a look at how it gets the options to display, and how it applies a search.

    Array support is something that is on my list of things to do, but I'd welcome a PR which adds this feature as I don't know when I'll get some free time to work on that.

    There is no documentation for adding plugins as of yet (another thing that is on the list of things to do). However the code base is Typescript and (I think) well documented and annotated.

    Allan

Sign In or Register to comment.