You have unlimited access as a PRO member
You are receiving a free preview of 3 lessons
Your free preview as expired - please upgrade to PRO
Contents
Recent Posts
- Object Oriented Programming With TypeScript
- Angular Elements Advanced Techniques
- TypeScript - the Basics
- The Real State of JavaScript 2018
- Cloud Scheduler for Firebase Functions
- Testing Firestore Security Rules With the Emulator
- How to Use Git and Github
- Infinite Virtual Scroll With the Angular CDK
- Build a Group Chat With Firestore
- Async Await Pro Tips
Simple Firebase Pagination With AngularFire2
Episode 18 written by Jeff DelaneyPagination allows users to easily navigate through a large collections, but it is a surprisingly complex challenge to solve with Firebase, especially if you want page numbers for a realtime data steam. In SQL, we can use the OFFSET
operator to sort through a table of static data. In Firebase NoSQL, we don’t have this luxury. I’ve seen several blog posts and StackOverflow answers dedicated to this question - all of them wrong - so I wanted to give my take on it
Implementation Strategy
In this lesson, pagination works by pulling the first N+1 items from the database, where N
is the number of items on the page and +1
the starting point for the next query. The advantage is that it works with data collections of any size :smile: . The drawback is page numbers are not possible, just next/previous buttons :sad: .
Possible Alternatives
If you really need numbered pagination, I see as the following two options as potentially viable.
(1) Load the entire collection into memory, then slice it into pages client side. This works fine on small datasets.
(2) Maintain a separate database collection of starting page keys sorted the way you want, which you query before getting the actual data for each page. This could be flexible, but potentially a maintenance nightmare because you would have to update the collection after each create or delete operation.
Building the Firebase Paginator
Let’s get started by generating some resources with the Angular CLI.
ng g service comments |
Currently, our database has comments nested under their associated blog post.
comments |
Comment Service
The CommentService
is going to return a list observable. The offset
is the number of comments to show on each page. The startKey
is where the query will start (undefined for first page) - the same idea as a SQL OFFSET, just with keys instead of numbers. We add 1 extra item to the offset because we need its key as the starting point for the next page. For example, we pull 3 items, show the user first 2 items, then use the last item’s key as the starting point for the next page.
comments.service.ts
import { Injectable } from '@angular/core'; |
Comment List Component
The template simply loops over the comments, then uses a couple buttons for next and previous.
comments-list.component.html
<div *ngFor="let comment of comments"> |
Lodash is essential for handling the array operations in the component. Most of the functions are self-explanatory, but check out the docs if you’re unsure.
First, subscribe to the observable in the component TypeScript instead of unwrapping it in the template with the | async
pipe.
When the observable emits, slice off the first 2 comments, then set the nextKey
from the 3rd value. If no 3rd comment is present, the end of the collection has been reached and the button can be disabled.
Cool, that will move forward through the collection. But how do we go backwards?
To go backwards, we need to maintain a running list of prevKeys
. Each time the user goes forward, the we push a new key to the array. When the user wants to go backwards, we pop the last element from the array as the starting key, then drop it. When the array is empty, the first page has been reached the prev button can be disabled.
comments-list.component.ts
import { Component, OnInit } from '@angular/core'; |
That’s it for pagination. Stay tuned for an alternative lesson about infinite scroll style pagination.