primefaces / primeng

The Most Complete Angular UI Component Library
https://primeng.org
Other
10.07k stars 4.54k forks source link

p-tree with filter - filter text not displayed until filter complete #16014

Open awdorrin opened 1 month ago

awdorrin commented 1 month ago

Describe the bug

I have a tree with 4 levels of depth, containing nearly 5000 leaf nodes. When I enter text into the search filter, what I type is not displayed until after the filtering pass is completed.

Here are some examples when I search for the work Program in Chrome

I think this may be due to lack of a debounce to collect multiple characters being typed, and perhaps the search triggering on key down, rather than key up?

This idea seems like it may be what is going on, based on what I see when I use Firefox (v115.13.0) When I type the word 'Program' in Firefox, I see a faster response time overall ~11 seconds, vs 18 for Chrome, and I see the following:

Environment

Running locally on my Windows 11 system from VS2022, or deployed to a Windows 2016 Server within IIS.

In stackblitz example builds 4 layer menu, 5000 leaf nodes. Type in the word 'Program' - the 'P' will be displayed, then it will take 10-15 seconds The stackblitz is A LOT slower than my actual code, because every leaf node contains the word Program. Where in my real code, only a subset of about 400 nodes contain the word 'Program' in a label. In my real code, it has the advantage of a lenient filter that stops comparing children if a match is found in a parent node.

Reproducer

https://stackblitz.com/edit/github-gswfqp

Angular version

17.3.11

PrimeNG version

17.18.4

Build / Runtime

Angular CLI App

Language

TypeScript

Node version (for AoT issues node --version)

18.30.3

Browser(s)

Chrome 126.0.6478.127

Steps to reproduce the behavior

Create a tree with a lot of nodes (several thousand), enable filter, type text into filter and observe text not being displayed until filter is rendered. 1 to 5 seconds in my experience, depending on the search text entered.

Expected behavior

Text in filter box should display before filtering starts, so user sees what they are typing. Should be some amount of debounce time to reduce filtering by single characters. (Configurable, but min 250ms) Option to wait for 'enter' key before searching?

awdorrin commented 1 month ago

I'm wondering if replacing the filter input's (input)="_filter($event.target.value)" method with the following would resolve the issue:

ngOnInt() {
  fromEvent(this.filterViewChild.nativeElement, 'input')
  .pipe(debounceTime(300), distinctUntilChanged())
  .subscribe((event: any) => {
    this._filter(event.target.value);
  });
}

and then tweaking the _filter method with a setTimeout in order to allow the characters entered to be displayed in the HTML Input quicker:

  public _filter(value: string) {
    setTimeout(() => {
        let filterValue = value;
        if (filterValue === '') {
            this.filteredNodes = null;
        } else {
            this.filteredNodes = [];
            const searchFields: string[] = this.filterBy.split(',');
            const filterText = ObjectUtils.removeAccents(filterValue).toLocaleLowerCase(this.filterLocale);
            const isStrictMode = this.filterMode === 'strict';
            for (let node of <TreeNode<any>[]>this.value) {
                let copyNode = { ...node };
                let paramsWithoutNode = { searchFields, filterText, isStrictMode };
                if (
                    (isStrictMode && (this.findFilteredNodes(copyNode, paramsWithoutNode) || this.isFilterMatched(copyNode, paramsWithoutNode))) ||
                    (!isStrictMode && (this.isFilterMatched(copyNode, paramsWithoutNode) || this.findFilteredNodes(copyNode, paramsWithoutNode)))
                ) {
                    this.filteredNodes.push(copyNode);
                }
            }
        }

        this.updateSerializedValue();
        this.onFilter.emit({
            filter: filterValue,
            filteredValue: this.filteredNodes
        });
    }, 0);
  }
awdorrin commented 1 month ago

I have a bit of a work-around by using treetable, with one column, but still working through the differences. Filter works a lot better, although it would be nice to find a way to catch the start and end of filter event, so I can trigger a progress bar, progress spinner or an animated 'searching' icon...