How to Use Infinite Scroll with Angular and Firestore

From WikiHTP

There are many ways to program an Infinite Scroll with Angular and Firestore , we will choose the simple way, making use of Arrays, so we can control our application with a very simple code, and it will work just as well as another made with Observables, something we will see later.

Our project will be developed with AngularCLI, the only thing that we are going to install are a couple of dependencies, among them AngularFire and ngx-infinite-scroll, so we are going to execute the following command within our project.

npm install ngx-infinite-scroll firebase angularfire2 lodash --save

Pagination with AngularFire[edit]

Now we are going to create a very simple service with the following command which will help us to paginate the data using Firestore databases.

ng g service afire

We open it and add the following code that only contains one method which will help us to page.

import { Injectable } from '@angular/core';
import {AngularFirestore, DocumentChangeAction} from 'angularfire2/firestore';

@Injectable({
  providedIn: 'root'
})
export class AfireService {

  constructor(
    private afs: AngularFirestore,
  ) {}

  paginate (limit: number, last: string):  Observable<DocumentChangeAction<any>[]> {
     return this.afs.collection('todos', (ref) => (
      ref
        .where('id', '<', last)
        .orderBy('id', 'desc')
        .limit(limit)
     )).snapshotChanges();
  }
}

The paginate method will return the paginated records correctly with a limit and an offset.

new component for paginate method[edit]

Now we are going to create a new component to use the paginate method and format the data correctly and leave them ready to move to the template.

ng g component pagination -m app

We open it and add the following.

import { Component, OnInit } from '@angular/core';
import {AfireService} from '../afire.service';
import {map} from 'rxjs/operators';
import * as _ from 'lodash';

@Component({
  selector: 'app-pagination',
  templateUrl: './pagination.component.html',
  styleUrls: ['./pagination.component.css']
})
export class PaginationComponent implements OnInit {

  todos: Array<any> = [];
  batch: number = 4;
  last: any = Date.now();
  empty: boolean = false;
  loading: boolean = false;

  constructor(public aFireService: AfireService) {}

  ngOnInit() {
    this.fetchTodosPaginated();
  }

  onScroll () {
    this.loading = true;
    setTimeout(() => {
      this.fetchTodosPaginated();
      this.loading = false;
    }, 1500);
  }

  fetchTodosPaginated () {
    this.aFireService.paginate(this.batch, this.last).pipe(
      map(data => {
        if ( !data.length) {
          this.empty = true;
        }
        let last = _.last(data);
        if (last) {
          this.last = last.payload.doc.data().id;
          data.map(todoSnap => {
            this.todos.push(todoSnap.payload.doc.data());
          })
        }
      })
    ).subscribe();
  }
}
  • fetch AllPaginated: pushes new all to the array all if it exists.
  • onScroll: will run every time the page touches the end of the scroll.


Finally, we just have to define the content of the template, so we can add the following code and everything will work.

<div *ngIf="todos.length > 0">
  <table class="table">
    <thead>
    <tr>
      <th>ID</th>
      <th>TODO</th>
    </tr>
    </thead>
    <tbody>
    <tr *ngFor="let todo of todos">
      <td>{{ todo.id }}</td>
      <td>{{ todo.todo }}</td>
    </tr>
    </tbody>
  </table>

  <div class="row justify-content-center" *ngIf="todos.length > 0 && !empty">
    <div *ngIf="loading" class="alert alert-warning d-block text-center position-absolute">Cargando datos...</div>
    <div class="search-results"
         infiniteScroll
         [infiniteScrollDistance]="2"
         [infiniteScrollThrottle]="50"
         (scrolled)="onScroll()">
    </div>
  </div>

  <div *ngIf="empty" class="alert alert-primary d-block text-center">Ya no hay más datos!</div>

</div>

We go through all of them to show them in an html table.

We use the infiniteScroll directive by calling the onScroll method in the scrolled event. If you have followed all the steps you will have the Infinite Scroll in angular

About This Tutorial

This page was last edited on 5 February 2019, at 21:09.