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: 15Questions: 3Answers: 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 accepted answers - jump to:

Answers

  • allanallan Posts: 65,206Questions: 1Answers: 10,804 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: 15Questions: 3Answers: 0
    edited September 16

    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,206Questions: 1Answers: 10,804 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

  • ChadChaddingtonChadChaddington Posts: 15Questions: 3Answers: 0

    Hi again! So I've been looking at the docs and repo trying to figure out how to best add the feature, but I'm not sure how to test it?

    How does one run a version of datatables that uses the cloned version of the repo instead of the stable one installed using npm?

    And, from someone who has worked on several team projects (I'm...pretty much fresh out of college) - it is a breath of fresh air to try to figure out code that has comprehensible documentation, so thank you.

  • ChadChaddingtonChadChaddington Posts: 15Questions: 3Answers: 0
    edited September 22

    Please ignore that last comment about the checklist, I'm sorry

  • allanallan Posts: 65,206Questions: 1Answers: 10,804 Site admin

    giving them an index in the reverse order of when they were added?

    I don't understand the question on those lines I'm afraid. Id isn't assigning an index there, and the container loop is going through the array incrementing.

    Could you clarify what you mean?

    Allan

  • ChadChaddingtonChadChaddington Posts: 15Questions: 3Answers: 0

    Sorry that was me not noticing the extra = for some reason: I was reading i === opts.length - 1 as i = opts.length - 1, so it took me a little while to realize that Checklist added items with information as to whether to update or not, rather than their index.
    (I did try to delete that comment to avoid spam, but the forum didn't let me)

    But on that topic: I was going through the code again - can you confirm that it is only on the reloadOptions function that duplicate options are discarded/filtered out? It was the only place where I found that happened, and I wanted to use it as a reference for filtering out duplicate tags in different cells

    (e.g.: one cell displays [TagA] and another [TagA, TagB], with the final checklist containing [TagA, TagB] rather than [TagA, TagA, TagB]).

    I could find filtering neither:
    * On the searchList source code (where the setOptions function just adds all options to the checklist)
    * Nor on the Checklist itself (which uses the array push method to add content to it).

    Thank you in advance

  • allanallan Posts: 65,206Questions: 1Answers: 10,804 Site admin

    Ah! Yes, that is a check to see if it is at the end of the loop and therefore do the extra calculations.

    • can you confirm that it is only on the reloadOptions function that duplicate options are discarded/filtered out?

    If there are no options given, and therefore the list needs to get the options from the table, then yes, in that block of code to get the options it does de-duplication. If the options are given (from the client-side options parameter or from the server-side), then there is no de-duplication.

    I could find filtering neither:

    This is the block where the filter is actually applied.

    Allan

  • ChadChaddingtonChadChaddington Posts: 15Questions: 3Answers: 0
    edited September 23

    Thank you so much for all your help these past few days!

    Lastly, regarding adding the new feature:

    1. How does one run a version of datatables that uses the cloned version of the repo instead of the stable one installed using npm? How do I test that things are working before submitting a pull request?
    2. Is it okay to I add es2019 to the lib section in tsconfig.json file? It's required to use the Array flat() method, which would be useful for managing a searchListArray's cell contents.

    3. I'm working on a separate fork for the feature, though I haven't pushed any of my commits onto it yet (again, I have not figured out how to test them) to later do a pull request to the main project. Is it preferable to:
      3.A. Wait til I figure out how to test to push them to the fork so they may be reviewed once I know for a fact they work?
      3.B. Push them to a separate branch so they're accessible, only merging them to the fork's main branch once I've tested them?
      3.C. Wait til I figure out how to test to push them to a separate branch?

  • allanallan Posts: 65,206Questions: 1Answers: 10,804 Site admin
    Answer ✓

    1) The build instructions are here.

    2) Yes, go for it. as long as the built file supports browser's 10 years back, I'm okay with polyfills being included.

    3) To be honest, that doesn't matter from my perspective. Your PR can come from main or any other branch on your fork. Commit to your fork however you feel comfortable.

    Allan

  • ChadChaddingtonChadChaddington Posts: 15Questions: 3Answers: 0

    Thank you for everything!! I finally got the hang of things, I believe :smiley:

    (Sorry for the delay; I was under the erroneous impression that the community preferred to not use messages exclusively for thanking people no matter how deserved, a-la stack overflow who doesn't allow greetings. I'm glad it's not the case.)

  • allanallan Posts: 65,206Questions: 1Answers: 10,804 Site admin

    Pfft no. I'll take all the thanks I can get ;).

    Great to have you building the software. For what it is worth I am in the process of updating DataTables to build with Typescript rather than my bash scripts, so things will change.

    Allan

  • ChadChaddingtonChadChaddington Posts: 15Questions: 3Answers: 0
    edited October 7

    :D :star: roger

    It's a little intimidating since it's my first time working on an established project like this (outside of classes, anyway), but I'm enjoying the challenge and opportunity to add to it! It helps that there's extensive documentation and that community support is so present.

    I've looked into building with Typescript just now to get a feel for it (I've only used bash before) since you'll be updating DataTables to build with Typescript. Learning a lot, these past few weeks!

Sign In or Register to comment.