Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clear filter on table calls multiple times onLazyLoad #9980

Closed
elnicopons opened this issue Mar 8, 2021 · 10 comments
Closed

Clear filter on table calls multiple times onLazyLoad #9980

elnicopons opened this issue Mar 8, 2021 · 10 comments
Assignees
Labels
LTS-PORTABLE Type: Bug Issue contains a bug related to a specific component. Something about the component is not working
Milestone

Comments

@elnicopons
Copy link

[x] bug report
[ ] feature request
[ ] support request

Current behavior
Calling table.clear() calls multiple times the onLazyLoad event (1 per column + 1 time more)

Expected behavior
Calling table.clear() must clear the applied filters/order and call onLazyLoad 1 time

Minimal reproduction of the problem with instructions
Use a p-table with [lazy]="true". Declare a button wich click event call the clear method of the table.

What is the motivation / use case for changing the behavior?
Once the filter is cleared, the request must by fired only once to prevent performance issues

  • Angular version: 11.0.5

  • PrimeNG version: 11.2.3

  • Browser: [Chrome 89]

@yigitfindikli yigitfindikli added the Status: Pending Review Issue or pull request is being reviewed by Core Team label Mar 9, 2021
@themhassany
Copy link

themhassany commented Mar 14, 2021

with primeng: ^11.3.1, i also confirm the bug. previously i was using 11.2.1, and this bug didn't exists.

Calling table.reset() has also the same problem.

@satoshisound
Copy link

Ran into this issue as well with 11.3.2.

@pkalkman
Copy link

Any news on this, just confirmed that the bug is still there in 11.4.2

@ikanters
Copy link

Workaround can done using rxjs stream:

  1. Define a new stream property (and subscriptions to keep track of the subscribe):
lazyLoadStream = new Subject<LazyLoadEvent>();
subscriptions = new Subscription()l
  1. In the ngOnInit subscribe to that stream. (I'm using lodash here for equality check.)
ngOnInit() {
 this.subscriptions.add(
     this.lazyLoadStream
       .pipe(distinctUntilChanged(_.isEqual))
       .subscribe(event => this.load(event)),
   );
}
  1. In the onLazyLoad put a clone (I'm using lodash) of the event on the stream. A clone is needed for the distinctUntilChanged:
  onLazyLoad(event: LazyLoadEvent) {
    this.lazyLoadStream.next(_.cloneDeep(event));
  }
  1. Do the actual loading of the data in the load method.
  2. Don't forget to unsubscribe:
ngOnDestroy() {
    this.subscriptions.unsubscribe();
  }

@sasynkamil
Copy link

I'm attaching StackBlitz (based on your showcase) of this issue (lazy & table reset programically).

app.component.html

<p-button label="Reset table" (click)="resetTable()"></p-button>
<hr/>
<p-table
    #customerTableRef 
    [value]="customers"
    [lazy]="true"
    (onLazyLoad)="loadCustomers($event)" 
    [paginator]="true"
    [rows]="10"
    [totalRecords]="totalRecords"
    [loading]="loading"
    sortMode="multiple">
    <ng-template pTemplate="header">
        <!--
        <tr>
            <th pSortableColumn="name">Name <p-sortIcon field="name"></p-sortIcon></th>
            <th pSortableColumn="country.name">Country <p-sortIcon field="country.name"></p-sortIcon></th>
            <th pSortableColumn="company">Company <p-sortIcon field="company"></p-sortIcon></th>
        </tr>
        -->
        <tr>
            <th>Name</th>
            <th>Country</th>
            <th>Company</th>
        </tr>        
        <tr>
            <th>
                <p-columnFilter type="text" field="name"></p-columnFilter>
            </th>
            
            <th>
                <p-columnFilter type="text" field="country.name"></p-columnFilter>
            </th>
            <th>
                <p-columnFilter type="text" field="company"></p-columnFilter>
            </th>
        </tr>
    </ng-template>
    <ng-template pTemplate="body" let-customer>
        <tr>
            <td>{{customer.name}}</td>
            <td>{{customer.country.name}}</td>
            <td>{{customer.company}}</td>
        </tr>
    </ng-template>
</p-table>

app.component.ts

import {Component, ViewChild} from '@angular/core';
import { CustomerService } from './customerservice';
import { Customer } from './customer';
import { FilterUtils } from 'primeng/utils';
import { LazyLoadEvent } from 'primeng/api';
import { PrimeNGConfig } from 'primeng/api';
import {Table} from 'primeng/table';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html'
})
export class AppComponent { 
    datasource: Customer[];

    customers: Customer[];

    totalRecords: number;

    cols: any[];

    loading: boolean;

    @ViewChild('customerTableRef') customerTableRef: Table | undefined;

    constructor(private customerService: CustomerService, private primengConfig: PrimeNGConfig) { }

    ngOnInit() {
        //datasource imitation
        this.customerService.getCustomersLarge().then(data => {
            this.datasource = data;
            this.totalRecords = data.length;
        });

        this.loading = true;
        this.primengConfig.ripple = true;
    }

    loadCustomers(event: LazyLoadEvent) {
        console.log('onLazyLoad : loadCustomers');
        this.loading = true;

        //in a real application, make a remote request to load data using state metadata from event
        //imitate db connection over a network
        setTimeout(() => {
            if (this.datasource) {
                this.customers = this.datasource.slice(event.first, (event.first + event.rows));
                this.loading = false;
            }
        }, 1000);
    }

    resetTable(): void {
      console.log('resetTable');
      this.customerTableRef?.reset();
    }
}

Once I click on the button which triggers this.customerTableRef?.reset();:

resetTable
onLazyLoad : loadCustomers
onLazyLoad : loadCustomers
onLazyLoad : loadCustomers
onLazyLoad : loadCustomers

@kingbe01
Copy link

So I just tied to update to Primeng 12 and this issue still exists. Why has this not been addressed yet as it is a big bug and makes lazy loading with filters completely useless.

@ThomasPrikrylBE
Copy link

ThomasPrikrylBE commented Oct 4, 2021

Have there been any updates on this issue?

EDIT 1:
Also: Shouldn't the reset function also 'restore' to the default order that was set in the beginning? Or in other words: How does one reset the table and sort it (so that the sortable columns visually represent this) in one go (aka one lazyload) ? Maybe in a configurable way like [restoreDefaultOrderOnReset]="true" or sth

EDIT 2:
Here is a workaround for the problem. It should work but I would much rather prefer if the table itself could handle this.

@ronbiter
Copy link

using 13.0.0-rc.2 and bug still exists. would be great if it is fixed!! really useful feature if it worked as expected.

ronbiter added a commit to ronbiter/primeng that referenced this issue Dec 20, 2021
table with lazyload and filtering -
table reset triggers lazy load as the amount of filters the table has
@fatihdogmus
Copy link

fatihdogmus commented Dec 22, 2021

@ikanters's solution is really nice but was missing a piece for me. If multiple filters were filled and you called clear(), since the clearing of filters happen one by one, the events that are triggered for each filter is different since it is still in the process of clearing it. It throws the event with information of intermediate step, so there were still duplication in the events. So what I did in my clear() function was to first disable the lazy property so that no event will be thrown, cleared table, activated lazy and cleared again to trigger the event. Since we are deduplicating events, only one event will pass the filter when we call the event the second time. This is VERY dirty and hacky solution and I felt bad after implementing it, but till we get a fix, this was the only thing that worked for me. Here's the code for clear function, which is built on top of @ikanters's solution:

clear(table: Table) {
  table.lazy = false;
  table.clear();
  table.lazy = true;
  table.clear();
}

Table is the reference of the actual table.

The fix shouldn't be that hard, I think this needs to be prioritized for next version, considering that the original issue is from almost a year ago.

@yigitfindikli yigitfindikli added this to the 13.Future milestone Mar 7, 2022
@yigitfindikli yigitfindikli self-assigned this Mar 7, 2022
@yigitfindikli yigitfindikli modified the milestones: 13.Future, 13.3.0 Mar 10, 2022
@yigitfindikli yigitfindikli added Type: Bug Issue contains a bug related to a specific component. Something about the component is not working LTS-PORTABLE and removed Status: Pending Review Issue or pull request is being reviewed by Core Team labels Mar 15, 2022
@kalyanipullela
Copy link

kalyanipullela commented Feb 28, 2023

Any solution to the above issue on the lazyload?
Still persists in v12

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
LTS-PORTABLE Type: Bug Issue contains a bug related to a specific component. Something about the component is not working
Projects
None yet
Development

No branches or pull requests