Tips for efficiently displaying and handling vast quantities of information within an Angular 2 table

I am currently working on the development of an Angular 2 application that requires displaying a large amount of data in a scrollable table.

The data is stored in an array within my component class:

export class AppComponent { 

    clients: any[] = [];

    constructor(){
        for (var i = 0; i < 10; ++i) {
           this.clients.push({
               id: i,
               name: 'Client' + i,
               address: 'Address of client ' + i,
               phone: '(51) 5454-4646'
           });
        }
    }
}

To display the data, I utilize ngFor in my layout:

       <div style="height:600px;overflow:scroll">

          <data-table>

          <th>Id</th>
          <th>Name</th>
          <th>Address</th>
          <th numeric>Phone</th>

          <tr *ngFor="let client of clients">
            <td>{{ client.id }}</td>
            <td>{{ client.name }}</td>
            <td>{{ client.address }}</td>
            <td>{{ client.phone}}</td>
          </tr>

        </data-table>
      </div>  

This application needs to load and display a large volume of data in a table with potentially tens of thousands of rows and multiple columns. However, there are performance issues causing significant lag during loading and execution.

In this scenario, pagination is not an option and the scroll feature is essential. I aim to maintain the appearance of the scroll thumb size and position as if all data is loaded, even if I need to implement a workaround such as loading only a portion of the data.

I seek guidance on the best practices to effectively handle this task without experiencing slowdowns.

Answer №1

My suggestion would be to transform your table into a component and switch the change detection strategy to "on push". This adjustment will help Angular minimize performance expenses.

Answer №2

It's worth noting that the amount of data you're dealing with is significant, which could result in higher costs for users due to the need to request and download a large volume of information.

To address this issue, I suggest breaking down the data into smaller sections with pagination enabled. Displaying around 100 records per page can greatly enhance readability and user experience.

In Angular 1.x.x, you have the option to utilize the limitTo filter for restricting results. For Angular 2.x.x, consider using the slice filter instead.

Your modified template could resemble the following structure, though its functionality may require further testing:

      <th>Id</th>
      <th>Name</th>
      <th order="desc">Address</th>
      <th numeric>Phone</th>
      <th>Actions</th>

      <tr *ngFor="let client of clients | slice:pageStart:100">
        <td>{{ client.id }}</td>
        <td>{{ client.name }}</td>
        <td>{{ client.address }}</td>
        <td>{{ client.phone}}</td>
        <td>Actions</td>
      </tr>

      <button *ngIf="pageStart >= 100" (click)="prevData()">Previous</button>
      <button *ngIf="pageStart < clients.length" (click)="NextData()">Next</button>
    </data-table>

The corresponding component implementation might appear as follows:

export class DataTable {
  // Relevant code segments are omitted here for brevity
  pageStart = 0;

  nextData() {
    this.pageStart += 100;           // Retrieve the subsequent 100 records
  }

  prevData() {
    this.pageStart -= 100;          // Acquire the preceding 100 records
  }
}

Alternatively, you could explore implementing some form of infinite scrolling as an alternative solution.

Answer №3

Though it's a bit late, my hope is that I can assist others who come across this.
I've implemented Richard Hamilton's pagination example with some modifications.

Alternatively, you could consider using infinite scrolling as well.

       <div style="height:600px;overflow:scroll" (scroll)="onScroll($event)">

      <data-table>

      <th>Id</th>
      <th>Name</th>
      <th>Address</th>
      <th numeric>Phone</th>

      <tr *ngFor="let client of clients | slice:pageStart:pageEnd">
        <td>{{ client.id }}</td>
        <td>{{ client.name }}</td>
        <td>{{ client.address }}</td>
        <td>{{ client.phone}}</td>
      </tr>

    </data-table>
  </div>  

The key differences include the addition of a scroll event listener and the absence of pagination buttons.

export class DataTable {
  pageStart:number = 0;
  pageEnd:number = 100;
  pageHeight:number = 30;
  pageBuffer:number = 100;

  onScroll( event, doc )
  {
    const scrollTop = event.target.scrollTop;
    const scrollHeight = event.target.scrollHeight;
    const offsetHeight = event.target.offsetHeight;
    const scrollPosition = scrollTop + offsetHeight;
    const scrollTreshold = scrollHeight - this.pageHeight;
    if( scrollPosition > scrollTreshold ){
      this.pageEnd+= this.pageBuffer;
    }
  }
}

This script monitors the position and adjusts the pageEnd value until reaching the end.
There may be a slowdown at some point with this solution.

I specifically required the infinite scrolling feature, so I can only suggest an idea to address the slowdown issue.

To prevent performance degradation, ensure that the rowHeight remains constant.
Calculate the maximum height of all rows and introduce an additional element for maintaining scroll availability.
Apply position:fixed; to the Data-Table to keep it visible consistently.
Determine appropriate positions for pageStart and pageEnd, allowing Slice to handle rendering efficiently.

While this approach seems viable, I have yet to test it.
It remains uncertain whether this method is suitable for regular use.

All the best. :)

Answer №4

If you're looking to efficiently load data without slowing down your page, I suggest trying out this lazy loading data pipe that I personally developed:LazyLoadPipe I put it to the test with a whopping 8128 records. By initially loading only 50 records for an immediate display on the DOM, I was able to seamlessly render the remaining records in the background.

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

Adding an external JavaScript library to a gateway project: A step-by-step guide

I've been attempting to integrate the Simpl5 JavaScript library into my gateway, but I have encountered some issues. I placed SIPml-api.js and SIPml.js in the webapp/content/scripts directory. In .angular-cli.json, I updated the scripts array as follo ...

Exploring TypeAhead functionality in Reactjs 18

I have encountered an issue while using react-bootstrap-typeahead version 5.1.8. The problem arises when I try to utilize the typeahead feature, as it displays an error related to 'name'. Below is my code snippet: import { Typeahead } from " ...

Is there a way to restrict the type of the value returned by URLSearchParams.get() to a specific union type?

When handling a search parameter in the URL, such as ?mode=view, it is important to validate the value of mode to ensure it is either 'edit' or 'view'. To achieve this, a custom type called ModeTuple is created and converted to a union ...

Error: The next.config.js file contains invalid options - The root value includes an unexpected property

I recently updated my next version from 10 to 12, and when I run the local development server, I encounter the following error in the terminal. As a result, the code fails to compile. How can I fix this issue? Invalid next.config.js options have been iden ...

Extract the array structure from the resolved promises using await with Promise.all()

When I receive the values returned by using await Promise.all() in the following manner: const [apple, banana] = await Promise.all<Object, Object>([ applePromise(), bananaPromise() ]).catch(error => next(error)); An error is triggered: T ...

How can I effortlessly retrieve the Current Route Path Name in Angular?

I needed to find out the current route's path name and discovered this simple solution. this.route.snapshot.firstChild.url[0].path Is there a more efficient method for achieving this? Appreciate any advice! ...

"Trouble with Python Selenium: Only extracting the first row while iterating through table data

I'm currently working on extracting the latest headlines from a news site and facing some challenges. The source I am using is: #saving button IDs to interact with buttons_ids = ['Tab21' , 'Tab22', 'Tab32'] #IDs of re ...

Display a customized modal showcasing the data of a particular user

Seeking advice on how to pass data to a modal based on a specific user. I have an array with user information and would like to display their name and email in a modal when the user is clicked on. Any suggestions on how to accomplish this? ...

How can I specifically activate the keydown event for alphanumeric and special characters in Angular7?

I am looking to create a keydown event that will be triggered by alphanumeric or special characters like #$@. <input type="text" style="width: 70%;" [(ngModel)]= "textMessage" (keydown) ="sendTypingEvent()" > However, I want to prevent the event ...

Avoid activating automatic save feature in Material UI data grid

After creating a data-grid and attempting to add records, I encountered an issue where pressing the TAB key automatically saved the data when focusing on the save button without manually pressing enter. How can this behavior be prevented so that manual con ...

Exploring Child Elements in Angular 2 Templates

I am working on a component and I need to access some child nodes from the template. I was able to access the details div, but I'm not sure why the code is functioning as it does. Can someone please explain what the Future class does? Also, why is the ...

The API call is failing when using getInitialProps in Next.js

I have been trying to retrieve data from an API using the getinitialprops method and axios However, it seems like my code is not working as expected. Here is a snippet of the relevant code in the file pages/index.tsx IndexPage.getInitialProps = async (ctx ...

Experiencing difficulty in triggering a NextUI Modal by clicking on a NextUI Table Row

In the process of developing my web portfolio, I am utilizing NextJS, TypeScript, and TailwindCSS. A key feature on my site involves displaying a list of books I have read along with my ratings using a NextUI table. To visualize this functionality, you can ...

When dealing with errors arising from API calls, Angular can be prone to throwing error messages

I am currently creating an Angular service class to interact with APIs. However, I am facing an issue when handling Internal server errors in the response and need to send an error message to the user. The services are designed for retrieval but encounteri ...

Effective ways to properly utilize the kendo-switch angular component for seamless rendering of the "checked" state

I recently started a new project in Angular 4 using CLI and incorporated various Kendo UI components. However, I encountered an issue with the kendo-switch component where it does not toggle correctly when set to checked=true. Instead of toggling from left ...

Error: No default Firebase App named '[DEFAULT]' exists. Please remember to call Firebase App.initializeApp() to create the app (app/no-app). This issue is located at the app

Currently, I am in the process of learning how to integrate Firebase Functions into an Ionic + Angular project. My goal is to develop a custom function that retrieves all games from a collection and returns an array sorted by the "count" attribute. Initia ...

Tips for utilizing playFromPositionAsync method with expo-av Video in React Native

While working with the Video Expo component, I came across a prop called playFromPositionAsync. In the Video.d.ts file, it is defined like this: export default class Video extends React.Component<VideoProps, VideoState> implements Playback { ... ...

Invoke a function within a component, within that very component

Hey there, I've got an Angular 2 component with a @HostListener. My goal is to call a method from this component using the @HostListener. Check out the code snippet below for my attempt at implementing this: The Component import { Component, Host ...

How to use Typescript to find the length of an array consisting of either strings or

I am trying to determine the length of a string or array, stored in a variable with the data type var stepData : string | string[]. Sometimes I receive a single string value, and other times I may receive an array of strings. I need the length of the array ...

The TypeScript declaration for `gapi.client.storage` is being overlooked

When I call gapi.client.storage.buckets.list(), TypeScript gives me an error saying "Property 'storage' does not exist on type 'typeof client'." This issue is occurring within a Vue.js application where I am utilizing the GAPI library. ...