primereact icon indicating copy to clipboard operation
primereact copied to clipboard

Dropdown, ListBox, MultiSelect: support custom filter function

Open VsevolodGolovanov opened this issue 5 years ago • 15 comments

Current behavior

Expected behavior Dropdown, ListBox and MultiSelect should support filterMatchMode="custom" with a custom filterFunction. Like DataTable and TreeTable do.

Minimal reproduction of the problem with instructions

Please tell us about your environment:

  • React version:
  • PrimeReact version: 4.2.2

  • Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]

  • Language: [all | TypeScript X.X | ES6/7 | ES5]

VsevolodGolovanov avatar Jul 13 '20 13:07 VsevolodGolovanov

Fixed with: https://github.com/primefaces/primereact/issues/3039

melloware avatar Jul 23 '22 14:07 melloware

Hi, I need add custom filter function in MultiSelect control. I need to use Regex to filter the data. I tried do this on two ways.

  1. I use filterTemplate as it is shown in documentation, but it is not possible to put regex value to option.filter().

const myFilterFunction = (event, options) => { let _filterValue = event.target.value; setFilterValue(_filterValue); options.filter(event); }

  1. In the filterTemplate I call my custom method (myFilterFunction) which change the options array in MultiSelect, but in this example I have a problem with filterring. When options array is empty I have a null instead of value in the MultiSelect control <InputText value={filterValue} ref={filterInputRef} onChange={(e) => myFilterFunction(e)} />

Is there any different way to use a custom filter method to filter data in MultiSelect control? I am grateful for the help. Regards,

Qcyk avatar Sep 15 '22 19:09 Qcyk

@melloware I realize this is a long-closed issue, but this issue was most definitely not fixed with that change.

The request here is to have a custom filter function which allows the user to do arbitrary filtering of their own. The linked PR only changed the way the filterable string is composed. That's not the same thing.

I want to be able to do a multi-pass filter for example, like "split the filter string by words (spaces) then check that every word appears in one of the results". That would be useful because we have tagging on our entries with text like Blah blah [Foo] so I want to be able to search "foo blah" and find that entry.

I could easily write that filter function myself, but as-is, it's impossible to do so with Dropdown, so I'm forced to reach to a totally different solution, like opening a Menu and managing my own list and make my own filter input, etc etc. Totally overkill for what would be simply fixed by allowing us to override the filter function.

francislavoie avatar Apr 13 '25 12:04 francislavoie

@francislavoie this was fixed by PrimeTek and not me. They considered it closed. It sounds like your use case is different I suggest opening a new ticket as this was closed 3 years ago.

Don't forget to include a stackblitz showing what you are trying to do.

melloware avatar Apr 13 '25 12:04 melloware

It was definitely closed by you:

Image

But anyway, reading both the OP and the comment just above mine, plus the fact that OP just 👍 my comment, I think this issue could easily just be reopened, because it was not actually solved as requested. I think our description of what we want is quite clear, and a Stackblitz wouldn't be useful because what we want to do is currently impossible anyway.

francislavoie avatar Apr 13 '25 12:04 francislavoie

Yes, this was about a custom filter function as in the ability to provide your own filtering predicate. Not about filter templates.

This is what I referenced in the issue description about the DataTable as an example:

return <Column filterField={filterField} filterMatchMode="custom" filterFunction={customFilterFunction} />;

function customFilterFunction(fieldValue: any, filterValue: string): boolean {
    ...
}

VsevolodGolovanov avatar Apr 13 '25 13:04 VsevolodGolovanov

I closed the ticket but the PR was by PrimeTek. I only closed it because they forgot 😀

So I had nothing to do with this feature.

melloware avatar Apr 13 '25 13:04 melloware

I don't see any link from this ticket to that PR other than your comment.

Can we please reopen this then?

francislavoie avatar Apr 13 '25 13:04 francislavoie

@francislavoie see: https://github.com/primefaces/primereact/issues/3039 by @cetincakiroglu of primetek.

melloware avatar Apr 13 '25 13:04 melloware

@francislavoie i re-opened but as you can see PrimeVue also does not support the feature you want: https://primevue.org/select/#filter

so you will most likely have to financially sponsor this via PrimeReact PRO: https://primereact.org/support/

OR provide a PR adding this capability.

Either way I look forward to it!

melloware avatar Apr 13 '25 13:04 melloware

@francislavoie @VsevolodGolovanov isn't that what onFilter event is for: https://primereact.org/dropdown/#api.Dropdown.DropdownFilterEvent

It says its for custom filtering basically letting you take control of the filter?

melloware avatar Apr 13 '25 13:04 melloware

I don't think onFilter allows you to affect filtering. It says "Custom filter event" meaning that the DropdownFilterEvent is a custom Dropdown-specific event type.

VsevolodGolovanov avatar Apr 13 '25 14:04 VsevolodGolovanov

Yep and it also looks like they deprecated filterTemplate which from his PR is where he used a custom filter function: https://github.com/primefaces/primereact/pull/3071/files#diff-93fc4b0a67c82b01cf498f38ee5d1102ee505fcb4c87c2d732cfe2a7acebf578

look at that example he writes his own filter function. But for some reason filterTemplate is deprecated with no explanation?

const filterTemplate = (options) => {
    let {filterOptions} = options;
    return (
        <div className="flex gap-2">
            <InputText value={filterValue} ref={filterInputRef} onChange={(e) => myFilterFunction(e, filterOptions)} />
            <Button label="Reset" onClick={() => myResetFunction(filterOptions)} />
        </div>
    )
}
const myResetFunction = (options) => {
    setFilterValue('');
    options.reset();
    filterInputRef && filterInputRef.current.focus()
}
const myFilterFunction = (event, options) => {
    let _filterValue = event.target.value;
    setFilterValue(_filterValue);
    options.filter(event);
}

melloware avatar Apr 13 '25 14:04 melloware

That's not a custom filter function, it's just a filter input updating function. It does not perform filtering and just delegates it to the library. That's why filterTemplate was never a solution for this.

francislavoie avatar Apr 13 '25 16:04 francislavoie

Yep PR or financial sponsoring welcome!

melloware avatar Apr 13 '25 16:04 melloware