Search code examples
angulartypescriptprimeng

PrimeNG lazy table override 'first' attribute whenever applying filtering


I am trying to initialize a primeNG table using queryParameters. e.g. http://my-url.com/table?name=Joe&first=20 should display data with name Joe, beginning at the 20th entry

That table use lazyLoading with [lazy]=true because of the sheer amount of data my backend can provides. When I initialize my component I read url parameters to apply filtering and pagination.

my-component.html

<p-table
  [paginator]="true"
  [lazy]="true"
  (onLazyLoad)="onLazyLoad($event)"
  [lazyLoadOnInit]="false"
  [(first)]="firstItem"
> <!-- ... -->

my-component.ts

export class MyComponent {
  @ViewChild('tableElement', {static: true}) pTableRef!: Table;

  protected firstItem = 0;

  ngOnInit(): void {
    this.route?.queryParamMap.pipe(first()).subscribe({
      next: (paramMap) => this.initStateFromParamMap(paramMap)
    });
  }

  ngAfterViewInit(): void {
    console.log("ngAfterViewInit called, this.firstItem = " + this.firstItem)
    // manually call onLazyLoad with dummy parameters if no filtering is done.
    // if filtering is done, p-table automatically calls onLazyLoad
  }

  private initStateFromParamMap(paramMap: ParamMap) {
    // note : this code is a just simplification of what is done
    this.lazyLoadingDoneAtLeastOnce = true;
    this.firstItem = firstItem;
    this.pTableRef.filter("Joe", name, 'equals');
    console.log("init finished, this.firstItem = " + this.firstItem)
  }

  onLazyLoad(event: LazyLoadEvent) {
    console.log("onLazyLoad called, this.firstItem = " + this.firstItem)
    // load specified data from backend
  }
}

output:

init finished, this.firstItem = 20
ngAfterViewInit called, this.firstItem = 20
onLazyLoad called, this.firstItem = 0

Calling this.pTableRef.filter("Joe", name, 'equals'); result in firstItem being set to zero, this is the basic behaviour if the user decides to manually apply a filter. However I do not want to reset the firstItem in this case.

Notes:

  • Swapping filter initialization and pagination initialization order does not change anything.
  • If no filtering is done. this.firstItem is not changed after ngAfterViewInit
  • Many unrelated element of my code have been omitted for readability

Solution

  • Looking through PrimeNG Table source code, I've found a boolean attribute named restoringFilter, if this is set to true, next filtering won't reset first item.

    By the way, calling filters trigger a timed out filtering, this is why multiples filtering done sequentially do not trigger multiple call to onLazyLoad, this is the same reason filtering (and therefore reinitialization of first item to 0...) was done after ngAfterViewInit.

    TL;DR, set restoringFilter to true when restoring filters

    this.pTableRef.restoringFilter = true;  
    this.pTableRef.filter("Joe", name, 'equals');
    

    This now works perfectly.