primefaces / primevue

Next Generation Vue UI Component Library
https://primevue.org
MIT License
10.51k stars 1.23k forks source link

Dropdown / Multiselect: lazy does not apply to filter (even though virtual scroller is lazy) #5471

Open mauritsderoover opened 7 months ago

mauritsderoover commented 7 months ago

Describe the bug

In our project we lazy load data in our dropdowns and our multiselect.

However, if you enable the virtual scroller with the setting isLazy enabled, the dropdown and multiselect still try to filter as usual. Since data is lazy loaded, this cannot be correct.

Our expected behaviour is that we either the we have the option to disable the default filtering or that it is disabled by default if you put the virtual scroller isLazy attribute to true.

Reproducer

notdoneyet

PrimeVue version

3.47.2

Vue version

3.x

Language

TypeScript

Build / Runtime

Vite

Browser(s)

Edge, Firefox, Chrome

Steps to reproduce the behavior

  1. Set up dropdown to lazy load data
  2. Set up dropdown to filter
  3. Try to filter

Expected behavior

Our expected behaviour is that we either the we have the option to disable the default filtering in the dropdown/multiselect or that it is disabled by default if you put the virtual scroller isLazy attribute to true.

Anubarak commented 6 months ago

One solution that worked for me is to include a custom filter "allow all"

import {FilterService} from "primevue/api";
FilterService.register('allow-all', () => true)

and use that filter match mode in the dropdown

<Dropdown
    :filter="true"
    filter-match-mode="allow-all"
    @filter="onFilter"

That way all items will always match, no matter what. My Custom onFilter method will then create an ajax request for the actual data and replace them

let searchTerm: string|null = null;
let prevResult: null|Array<Option|undefined> = null;
const onFilter = async (event: DropdownFilterEvent) => {
    // in case we do not search anymore, reset the options to the last result before searching
    if (event.value.length === 0 && Array.isArray(prevResult)){
        options.value = prevResult;
        return;
    }
    // remember the search term -> include that in your next lazy load pagination query
    searchTerm = event.value;
    // remeber the actual loaded items
    prevResult = options.value;

    // do your ajax stuff, load the data
    const res = await makeASearchRequest();

    // res should be an Array<Option|undefined> and be filled with undefined values for each missing result from the pagination, basically the same as your usual options
    options.value = res;
});
anchan42 commented 4 months ago

@Anubarak Thanks a lot. This works for me :)