Utilize PrimeNG's async pipe for lazy loading data efficiently

I have a significant amount of data (400,000 records) that I need to display in a PrimeNG data table. In order to prevent browser crashes, I am looking to implement lazy loading functionality for the table which allows the data to be loaded gradually.

The technologies I am utilizing for creating this table include:


Objective

My goal is to develop a lazy loading table similar to the one illustrated in the PrimeNG documentation. The data should be fetched from the server and displayed in the table incrementally as the user navigates through different sections.

The slight variation I intend to implement involves pre-fetching all data from the server before feeding it to the table component. This approach will allow me to select specific data from the datasource and present it to the user.


Issue at Hand

During my implementation efforts, I encountered a problem where the (onLazyLoad) function is only triggered once during the OnInit() phase before data retrieval from the server. Adding [lazyLoadOnInit]="false" prevents the function from being called altogether. Despite attempting to modify the [totalRecords] property upon data retrieval, I was unable to trigger the function.

I couldn't find any other suitable function within the PrimeNG p-table code to activate the (onLazyLoad) function. Am I overlooking something?


Code Snippet

public ngOnInit(): void {
  this.cars$ = this.carService.entities$; // = []
  this.carService.getAll(); // = [Car, Car, Car, Car] OR []
}

this.carService.entities$ initially holds a value of [] and gets populated with the outcome of the getAll() function call (it could also remain [] if there are no results).


To illustrate the issue, I've created a demonstration in StackBlitz. You'll notice that the data isn't displayed because the (onLazyLoad) event is only fired once when the initial data is empty.

It's worth noting that I'm employing the Angular Async pipe for transmitting data into my component, necessitating monitoring changes within an ngOnChanges() function.

Answer №1

To update the app.template, make the following changes:

<ng-container *ngIf="cars$ | async as data">
  <table-component [data]="data"></table-component>
</ng-container>

It appears that p-table lazyload does not trigger when the data changes, even when transitioning from undefined to object(array)

Visit stackblitz for more details

Update:

Retrieve data without using the async pipe:

  public ngOnInit(): void {
    this.carService.getAll().subscribe(data => this.data = data);
  }

Utilize ngOnChanges method for:

  public ngOnChanges(change: SimpleChanges): void {
    if(change.data) {
      if (change.data.currentValue) {
      this.datasource = change.data.currentValue;
      this.totalRecords = Array.isArray(change.data.currentValue) ? change.data.currentValue.length : 0;
      this.cars = this.datasource.slice(0, 10); // row number
      this.loading = false;
      }
    }
  }

Refer to this article for a guide on using async pipe and change detection

View another example on stackblitz

Answer №2

Special thanks to malbarmawi who helped me successfully update the table with new records. The only remaining issue was that lazy loading was being triggered too early, causing the data not to load properly.

In order to solve this problem, I realized that the table's methods are public and decided to inject the table as a @ViewChild so I could manually trigger the lazy loading process.

/**
 * A reference to the primeng table. Since all of it's methods are public we can
 * directly access the methods we need to trigger lazy loading correctly.
 */
@ViewChild(Table)
private tableRef: Table;

public ngOnChanges(change: SimpleChanges): void {
   if(change.data && change.data.currentValue) {
     this.datasource = change.data.currentValue;
     this.totalRecords = Array.isArray(change.data.currentValue) ? change.data.currentValue.length : 0;

     // Trigger lazy loading
     this.tableRef.onPageChange({ first: 0, rows: this.rows });
   }
}

With the implementation of lazy loading, I was also able to add a virtual scroller to enhance the performance of the table and smoothly manage my 400,000 records.

To achieve this, I simply updated the table properties to include the following (noting the virtual- properties):

<p-table [columns]="cols" [value]="cars" [scrollable]="true" [rows]="rows" [scrollHeight]="scrollHeight" [virtualRowHeight]="rowHeight" [virtualScroll]="true" [lazy]="true" (onLazyLoad)="loadCarsLazy($event)"  [totalRecords]="totalRecords" [loading]="isLoading"></p-table>

You can view a fully functional example of this code on StackBlitz.

Answer №3

Here is a different approach for handling loading indicators in Angular, inspired by this source. This method involves defining helper functions as shown below :

/**
 * Custom operator to detect the start and end of loading.
 */
export function interceptLoading<T>(onstart: () => void, onstop: () => void): (source: Observable<T>) => Observable<T> {
    return (source$: Observable<T>): Observable<T> =>
        source$.pipe(
            prepare(onstart),
            finalize(onstop)
        );
}

/**
 * Operator that triggers a callback when subscribed
 */
function prepare<T>(callback: () => void): (source: Observable<T>) => Observable<T> {
    return (source$: Observable<T>): Observable<T> =>
        defer(() => {
            callback();
            return source$;
        });
}

To implement this in your component, you can use it like so :

loading = true;

[...]

return this.service.getAll$().pipe(
     interceptLoading(() => this.loading = true, () => this.loading = false),
     map(...)
 );

Then, in your PrimeNG table component:

<p-table [loading]="loading" ...>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

A guide on converting array values to objects in AngularJS HTML

Here is my collection of objects: MyCart = { cartID: "cart101", listProducts : [ {pid:101, pname:"apple", price: 200, qty:3}, {pid:102, pname:"banana", price: 100, qty:12} ] } I have incorporated a form in ...

In Angular 12, the search button's response data does not appear in the template until the button is clicked twice

Check out my search input box and button code snippet <div class="col-lg-8"> <input #text class="form-control" placeholder="Search Customer" required/> </div> <button type="button" cla ...

The inner panel height does not extend to 100% when there is overflow

When pressing the submit button on a panel containing components, an overlay appears but does not cover the entire parent panel if scrolled to the bottom. Additionally, I want the spinner to always be centered, whether scrolling or not. I've tried usi ...

Avoid the import of @types definition without exports in TypeScript to prevent the error TS2306 (not a module)

I have spent a considerable amount of time trying to load a NodeJS library that has what I believe is a faulty type definition in the @types repository. The library in question is geolib and its types can be found in @types/geolib Although I am aware tha ...

Unable to activate parameter function until receiving "yes" confirmation from a confirmation service utilizing a Subject observable

Currently, I am working on unit tests for an Angular application using Jasmine and Karma. One of the unit tests involves opening a modal and removing an item from a tree node. Everything goes smoothly until the removeItem() function is called. This functi ...

Can the geocoder API/search box be utilized to locate specific markers on a map?

Incorporating Mapbox into an Angular application with a high volume of markers on the map (potentially thousands) and hoping to implement a search box for users to easily locate specific markers based on unique names and coordinates. Is this functionalit ...

Utilizing the useRef hook in React to retrieve elements for seamless page transitions with react-scroll

I've been working on creating a single-page website with a customized navbar using React instead of native JavaScript, similar to the example I found in this reference. My current setup includes a NavBar.tsx and App.tsx. The NavBar.tsx file consists o ...

Exploring the intricacies of extracting nested JSON data in TypeScript

Can someone help me with this issue? https://example.com/2KFsR.png When I try to access addons, I only see [] but the web console indicates that addons are present. This is my JSON structure: https://example.com/5NGeD.png I attempted to use this code: ...

Angular Observables do not update local variables when making API calls

For some reason, I cannot set a value in my local variable as expected. Here is the code snippet: export class memberComponent implements OnInit { member : Member = new Member(); constructor(private memberService: MemberService) {} ngOnInit() { ...

Best practices for handling HTTP requests in Angular 5

I'm currently developing multiple applications using Angular 5. My aim is to adhere to all the dos and don'ts of Angular. However, I'm facing some confusion regarding a few things. 1) What is the difference between this... this._http.g ...

Display identical text using JavaScript filter

My search filter highlight is currently displaying [object Object] instead of <mark>match values</mark> when replacing the values. This is the code I am using: this.countries.response.filter((val) => { const position = val.value.toLowerCa ...

Navigating through the keys of a parameter that can assume one of three distinct interfaces in TypeScript: a guide

Here is a function example: function myFunc(input: A | B | C) { let key: keyof A | keyof B | keyof C; for(key in input) { let temp = input[key]; console.log(temp); } } The definitions for A, B, and C are as follows: interfa ...

Invalid Redux store: Element type is not valid; a string type is expected

I am running into an issue while setting up the redux store with typescript for the first time. The error message I am encountering is: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) ...

Unauthorized access for POST request in WooCommerce API: 401 error

Let's start by examining the complete code to better understand the issue at hand. Here is the WooCommerce API authentication using the consumer key and secret from the file checkout.ts: this.WooCommerce = WC({ url:"http://localhost/ ...

When you use npm uninstall, it deletes the package from package.json, but it does not remove it from the node_modules directory

After attempting to uninstall a package using npm uninstall (package_name) -s The package was successfully removed from package.json but remained in the node_modules folder. How can I effectively remove these unused packages from the node_modules folder? ...

Discovering the power of Angular 2 with ngrx while putting my Reducer to the

Within my Reducer file: case PumpActionTypes.EnterLocalMode: return commandOne.upsertOne( {id: action.payload.id, changes: { local: false }}, state ); When testing, I aim to verify that the local property is indeed modified to false. My curr ...

The issue of LazyLoader delay not functioning as expected

I've implemented the LazyLoader plugin on my website using this code: <img src="http://www.bostonbakesforbreastcancer.org/wp-content/uploads/2012/03/sun.jpg" data-original="http://www.bostonbakesforbreastcancer.org/wp-content/uploads/2012/03/sun.j ...

Angular: issue with form validation - password matching is not functioning as expected

I have successfully implemented the registration form with basic validations The code I used can be found in: registration.html <form #registrationForm="ngForm" (ngSubmit)="onFormSubmit()"> ... <div class="form- ...

I can see the JSON data printing to the console in Ionic 3, but it doesn't display on

I seem to be facing a challenge with passing the 'item' to my search function in my Ionic 3 app. Although I was able to successfully connect to a json data file and print objects to the console, I am encountering an error message on the page that ...

UI and `setState` out of sync

Creating a website with forum-like features, where different forums are displayed using Next.js and include a pagination button for navigating to the next page. Current implementation involves querying data using getServerSideProps on initial page load, f ...