vincjo / datatables

A toolkit for creating datatable components with Svelte
https://vincjo.fr/datatables
MIT License
426 stars 14 forks source link

Expose custom comparison function, for filtering #28

Closed tcompa closed 1 year ago

tcompa commented 1 year ago

Hi there, and thanks for your support.

In https://github.com/vincjo/datatables/blob/master/src/lib/core/Context.ts, the method createFilteredRows uses stringMatch to filter relevant rows. We (me and @rkpasia, working on https://github.com/fractal-analytics-platform/fractal-web) would be interested in replacing stringMatch with a custom method. The reason for this is that we would like to select all rows where a certain column has a specific value.

Our use case is that (for instance) we have a column "ID", and rows with values 1, 2, ..., 10, 11, 12. We would like to be able to select the row with ID=1, without including the other IDs that match with 1 (e.g. 10 and 11). However, we don't see a way to achieve it with the current datatables. We could write a custom function, like

    private stringExactMatch(entry:string|Object, value: string) 
    {
    return entry === value
    }

but we could not use this comparison function instead of stringMatch. If there exists a way to achieve this, and we missed it, suggestions are welcome! :)


Would you consider including the possibility of overriding the stringMatch method as part of the Context class? How could this be exposed through the API, so that a user could replace stringMatch with a custom function? Could it be a comparisonFunction (undefined, by default) of Filters?

If this sounds interesting, we could try setting up a PR.

vincjo commented 1 year ago

Hi, Thx for your clear explanations. This is indeed a problem.

I found a quick solution by adding an opional "isEqualTo" param in the filter method.

When isEqualTo is set to true, the filter only returns 100% identical matches. Actually isEqualTo bypasses "stringMatch()" to apply return entry === value as you suggested

It's not published yet but can be tested here: https://vincjo.fr/datatables/test


Below is how it would be set :

Using Datahandler

hander.filter(
    value: string|boolean|number, 
    filterBy: string|Function, 
    isEqualTo = false
)
// example:
handler.filter(1, 'id', true)

Using <ThFilter/> component

<ThFilter {handler} filterBy="id" isEqualTo={true}/>
// short way:
<ThFilter {handler} filterBy="id" isEqualTo/>

Would this meet the need?

yayza commented 1 year ago

Definitely needed exact match filtering for things like IDs, is there a way I can pass a function to filter rows that start with the filter value instead of contains?

vincjo commented 1 year ago

Yeah, just realized that a custom function would be more relevant. So it would allow any isEqualTo, isGreaterThan, startsWith etc. comparison, as it was suggested initialy. Let's work on it

rkpasia commented 1 year ago

Thanks for the first draft @vincjo.

As you said

just realized that a custom function would be more relevant

It would be generally more useful for a user of this library to be able to specify its matching function in order to be more flexible.

We initially wrote this issue with an "ID-matching use-case" in mind, but for sure other cases could arise in the future. Introducing the possibility to specify a custom function could prevent other issues in the future related to this matter.

vincjo commented 1 year ago

So far I've written a static class that provides the most common comparisons i had in mind. https://github.com/vincjo/datatables/blob/master/src/lib/Comparator.ts

To resume the draft, it would be written like this:

import { Comparator } from '@vincjo/datatables'
export let handler

handler.filter(1, 'id', Comparator.isEqualTo)
handler.filter('john', 'first_name', Comparator.startsWith)
handler.filter(42, 'age', Comparator.isGreaterThanOrEqualTo)

// custom function: 
const customComparison = (entry, value): boolean => {
    return entry != value
}

handler.filter('john', 'first_name', customComparison)

Not yet totally convincing imo but it's progressing. Any idea or suggestion is appreciated

https://vincjo.fr/datatables/test

rkpasia commented 1 year ago

I think that it looks great!

vincjo commented 1 year ago

Custom comparison function has been released in v1.6.0 I'll keep debugging a few cases but it's usable.

https://vincjo.fr/datatables/examples/advanced-filters

tcompa commented 1 year ago

Great, thank you for the very rapid feedback!

We will report back if we observe any glitch, but I think this will fully cover our use case.