Ag-Grid Infinite Scroll Angular: Complete Implementation Guide with Examples

Learn how to implement Ag-Grid infinite scroll in Angular with step-by-step examples. This comprehensive guide shows you how to create server-side infinite scrolling for large datasets using Ag-Grid's infinite row model.

Ag-Grid Infinite Scroll Angular Implementation

What is Ag-Grid Infinite Scroll in Angular?

Ag-Grid infinite scroll Angular implementation allows you to efficiently handle large datasets by loading data on-demand as users scroll through your grid. This technique is essential for applications dealing with thousands or millions of records, providing smooth performance and excellent user experience.

In this comprehensive Ag-Grid infinite scroll example, I’ll show you how to implement server-side infinite scrolling in Angular using Ag-Grid’s infinite row model. This approach is perfect for displaying large datasets like GitHub issues, user lists, or any data that requires pagination.

Why Use Ag-Grid Infinite Scroll?

When dealing with large datasets in web applications, traditional approaches load all data at once, causing:

Ag-Grid infinite scroll Angular solves these problems by:

How Ag-Grid Infinite Scroll Works

Ag-Grid’s infinite scroll feature uses a combination of server-side pagination and row models. When users scroll down, Ag-Grid automatically requests the next batch of data from your server and appends it to the existing grid.

Available Row Models for Infinite Scroll

Ag-Grid provides three row models for infinite scrolling:

  1. Infinite Row Model (Community Edition) - What we’ll use in this example
  2. Server-Side Row Model (Enterprise Edition)
  3. Viewport Row Model (Enterprise Edition)

Since we’re using the Community Edition, we’ll implement the Infinite Row Model for our Ag-Grid infinite scroll example.

Prerequisites for Ag-Grid Infinite Scroll Angular

Before implementing Ag-Grid infinite scroll in Angular, ensure you have:

  1. Node.js version 12 or higher
  2. NPM or Yarn
  3. Angular CLI (@angular/cli)

Step-by-Step Ag-Grid Infinite Scroll Implementation

Step 1: Create Angular Project

ng new ag-grid-infinite-scroll-project
cd ag-grid-infinite-scroll-project

Step 2: Install Ag-Grid Dependencies

npm install @ag-grid-community/all-modules@^27.3.0 ag-grid-community@^29.2.0 ag-grid-angular@^29.2.0

Step 3: Configure Ag-Grid Styles

Add the following imports to your styles.scss file:

@import 'ag-grid-community/styles/ag-grid.css';
@import 'ag-grid-community/styles/ag-theme-balham.css';

Step 4: Import AgGridModule

In your app.module.ts:

import { AgGridModule } from 'ag-grid-angular';

@NgModule({
  imports: [
    AgGridModule,
    // ... other imports
  ]
})
export class AppModule { }

Step 5: Create TypeScript Interfaces

Create IGithubApi.ts file:

export interface IGithubIssue {
  created_at: string;
  number: string;
  state: string;
  title: string;
  id: string;
}

export interface IGithubApi {
  items: IGithubIssue[];
  total_count: number;
}

export interface IGithubIssueSearchParams {
  sort: string;
  order: 'asc' | 'desc';
  page: number;
  per_page: number;
}

Step 6: Implement Ag-Grid Infinite Scroll Component

Here’s the complete implementation for Ag-Grid infinite scroll in Angular:

import { Component, OnInit } from '@angular/core';
import { ColDef, ColumnApi, GridApi, GridOptions, GridReadyEvent, ICellRendererParams, IDatasource, IGetRowsParams } from "ag-grid-community";
import { IGithubApi, IGithubIssue, IGithubIssueSearchParams } from './IGithubApi';
import { Observable } from "rxjs";
import { HttpClient } from "@angular/common/http";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  gridApi: GridApi;
  columnApi: ColumnApi;
  gridOptions: GridOptions = null;
  searchParams: IGithubIssueSearchParams = {
    sort: 'created',
    order: 'desc',
    page: 1,
    per_page: 100
  }
  githubIssues: IGithubIssue[] = [];

  constructor(private _httpClient: HttpClient) {}

  ngOnInit() {
    this.initializeGridOptions();
  }

  private initializeGridOptions() {
    this.gridOptions = {
      getRowNodeId: data => data.id,
      columnDefs: this.getColumnDefinitions(),
      rowModelType: 'infinite',
      onGridReady: this.onGridReady.bind(this),
      overlayLoadingTemplate: `<span class="ag-overlay-loading-center">No issues found.</span>`
    };
  }

  onGridReady(params: GridReadyEvent) {
    this.gridApi = params.api;
    this.columnApi = params.columnApi;
    this.loadGithubIssues();
  }

  loadGithubIssues() {
    const dataSource: IDatasource = {
      rowCount: undefined,
      getRows: (params: IGetRowsParams) => {
        this.getRepoIssues(this.searchParams).subscribe(response => {
          this.githubIssues = response?.items;
          let lastRow = -1;
          if (response?.items?.length < this.searchParams?.per_page) {
            lastRow = this.githubIssues?.length;
          }
          this.searchParams.page = this.searchParams.page + 1;
          params.successCallback(this.githubIssues ?? [], lastRow);
        }, error => {
          params.failCallback();
        });
      },
    };
    this.gridOptions.api.setDatasource(dataSource);
  }

  getRepoIssues(searchParams: IGithubIssueSearchParams): Observable<IGithubApi> {
    const href = 'https://api.github.com/search/issues';
    const requestUrl = `${href}?q=repo:angular/components&sort=${searchParams?.sort}&order=${searchParams?.order}&page=${searchParams?.page}&per_page=${searchParams?.per_page}`;
    return this._httpClient.get<IGithubApi>(requestUrl);
  }

  private getColumnDefinitions(): ColDef[] {
    return [
      {
        flex: 1,
        field: 'id',
        headerName: 'ID',
        cellRenderer: (params: ICellRendererParams) => {
          if (params.value !== undefined) {
            return params.value;
          } else {
            return '<img src="https://www.ag-grid.com/example-assets/loading.gif" alt="loading">';
          }
        }
      },
      {
        flex: 1,
        field: 'created_at',
        minWidth: 130,
        tooltipField: 'Created',
        headerName: 'Created',
      },
      {
        flex: 1,
        field: 'state',
        minWidth: 130,
        tooltipField: 'State',
        headerName: 'State'
      },
      {
        flex: 1,
        field: 'number',
        minWidth: 130,
        tooltipField: 'Number',
        headerName: 'Number'
      },
      {
        flex: 1,
        field: 'title',
        headerName: 'Title',
        tooltipField: 'Title',
        minWidth: 140
      }
    ];
  }
}

Step 7: Create HTML Template

<ag-grid-angular
  *ngIf="gridOptions !== null"
  class="ag-theme-balham-dark"
  [style.height.%]="100"
  [style.width.%]="100"
  [gridOptions]="gridOptions">
</ag-grid-angular>

Key Features of This Ag-Grid Infinite Scroll Example

1. Infinite Row Model Configuration

rowModelType: 'infinite'

This tells Ag-Grid to use the infinite row model for server-side data loading.

2. Data Source Implementation

The IDatasource interface handles:

3. Row Node ID

getRowNodeId: data => data.id

Ensures proper row identification and prevents duplicates.

Testing Your Ag-Grid Infinite Scroll Implementation

Run your application:

npm run start

You should see:

Performance Benefits of Ag-Grid Infinite Scroll

This Ag-Grid infinite scroll example provides:

  1. Reduced Initial Load Time: Only loads first 100 records
  2. Memory Efficiency: Keeps only visible data in memory
  3. Smooth Scrolling: No lag when scrolling through thousands of records
  4. Scalability: Can handle millions of records without performance issues

Common Issues and Solutions

Issue 1: Data Not Loading

Issue 2: Duplicate Rows

Issue 3: Performance Issues

Advanced Ag-Grid Infinite Scroll Features

Custom Loading Templates

overlayLoadingTemplate: `<span class="ag-overlay-loading-center">Loading more data...</span>`

Error Handling

getRows: (params: IGetRowsParams) => {
  this.getRepoIssues(this.searchParams).subscribe(
    response => {
      // Success handling
    },
    error => {
      params.failCallback();
    }
  );
}

Custom Styling

You can customize the appearance using CSS:

.ag-theme-balham-dark {
  --ag-row-hover-color: rgba(255, 255, 255, 0.1);
  --ag-selected-row-background-color: rgba(0, 123, 255, 0.3);
}

Conclusion

This Ag-Grid infinite scroll Angular implementation provides a robust solution for handling large datasets efficiently. The infinite row model ensures smooth performance while maintaining excellent user experience.

Key Takeaways:

Resources:

This Ag-Grid infinite scroll example demonstrates best practices for implementing server-side infinite scrolling in Angular applications. Whether you’re building a data dashboard, admin panel, or any application requiring large data grids, this approach will provide the performance and user experience your users expect.

Ag-Grid table with infinite scroll showing GitHub issues

Next Steps: In my upcoming article, I’ll show you how to implement Ag-Grid server-side sorting to complement this infinite scroll functionality.


This comprehensive guide covers everything you need to know about implementing Ag-Grid infinite scroll in Angular. The step-by-step approach with practical examples makes it easy to follow and implement in your own projects.

Looking for a Full-Stack JavaScript Developer?

If you're hiring for a full-stack JavaScript developer position and found this article helpful, I'd love to contribute to your team! I specialize in modern JavaScript technologies including Node.js, NestJS, Angular, PostgreSQL, Docker, and Kubernetes, with extensive experience in RxJS, TypeScript, and building scalable web applications.

Let's connect:

  • 📧 Email: jobayer6735@gmail.com
  • Schedule a meeting
  • 💼 View my portfolio and other technical articles on this site

I'm passionate about writing clean, maintainable code and sharing knowledge with the developer community. If your company values technical excellence and continuous learning, I'd be excited to discuss how I can help your team succeed.

Jobayer

© 2025 Jobayer Ahmed. All rights are reserved.