How can Firebase be used to implement Infinite Scroll functionality?

      var self = this;
      var firebaseRef = new Firebase(baseUrl + '/sparks');

      firebaseRef.limitToLast(5).on('child_added', function(childSnapshot, prevChildKey) {
        self.addChild(childSnapshot); // adds post to a <div>
      });

https://i.sstatic.net/OySx9.png

Presently, my script fetches the latest 5 posts and keeps updating with new ones. Yet, I am interested in loading older posts too. I have a button that should trigger a function (which I need guidance on how to set up) for retrieving older posts. How can I retrieve these older posts?

(The arrow indicates my intention to fetch posts starting from the bottom moving upwards)

Answer №1

To achieve this, you'll need to approach it in a reverse manner. Begin by retrieving the results of your query for the first page and take note of the first item in the results:

firebaseRef.endAt().limitToLast(5).on('child_added', function(childSnapshot, prevChildKey) {
    self.addChild(childSnapshot); // adds post to a <div>
  });

Although you can't directly access child items by index with Firebase, you can store the key of an item and use that as a reference for initiating a subsequent query.

var firstKnownKey;
firebaseRef.orderByKey().limitToLast(5).on('child_added', function(childSnapshot, prevChildKey) {
    if (!firstKnownKey) {
      firstKnownKey = childSnapshot.key;
    }
    self.addChild(childSnapshot); // adds post to a <div>
});

You now have a variable called firstKnownKey that holds the key of the first item you encountered. To retrieve the previous set of children, provide this value to the endAt() method when executing the next query:

firebaseRef.orderByKey().endAt(firstKnownKey).limitToLast(5).on('child_added', function(childSnapshot, prevChildKey) {
    if (!firstKnownKey) {
      firstKnownKey = childSnapshot.key;
    }
    self.addChild(childSnapshot); // adds post to a <div>
});

Check out answers to similar questions from the past few days:

  • Can I get the nth item of a firebase "query"?
  • Firebase results range using startAt and endAt

Answer №2

Due to the inclusive nature of the endAt() function, I noticed that the last item was being repeated each time I executed infinite scroll. To address this issue, I made some adjustments based on a suggestion from Frank Van Puffen's solution.

I created a list called childrenVal to hold all the values, another list named childrenKey to store the keys, and initialized a variable called firstKnownKey, as recommended by Frank Van Puffen.

var childrenVal=[];
var childrenKey=[];
var firstKnownKey = "";

Initially, when making the query for the first time, I fetched the last 5 elements:

getFirst(){
    firebaseRef.orderByKey().limitToLast(5).once('value')
        .then((snap)=>{
            snap.forEach(childSnap => {
                childrenVal.unshift(childSnap.val());
                childrenKey.unshift(childSnap.key);
            });
            firstKnownKey = childrenKey[childrenKey.length-1];
        });
}

For subsequent queries, to prevent any repetition of the firstKnownKey, I implemented the following function:

exclude(key){
    return key.substring(0, key.length - 1) + String.fromCharCode(key.charCodeAt(key.length - 1) - 1)
}

And for the actual query execution, I utilized the following function:

getNext() {
    firebaseRef.orderByKey().endAt(exclude(firstKnownKey)).limitToLast(5).once('value')
        .then((snap) => {
            snap.forEach(childSnap => {
                childrenVal.unshift(childSnap.val());
                childrenKey.unshift(childSnap.key);
            });
            firstKnownKey = childrenKey[childrenKey.length - 1];
        });
}

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

Mapbox map not appearing in ionic live version

Currently, I am utilizing ionic along with react and incorporating the react-mapbox-gl library. During testing on localhost, everything works smoothly; however, after deploying the production build to Firebase hosting, the website only displays a grey blan ...

Exploring the changes in rootscope with AngularJS

I am attempting to connect to $rootscope in order to establish presence on a different server when the user logs in. Below is the code for my module. angular.module('presence', [ ] ) .run(function ($rootScope) { $rootScope.$watch($rootSc ...

Utilizing React to dynamically load JSON data and render a component

I am currently facing a challenge in rendering a React component that includes data fetched from a JSON using the fetch() method. Although the API call is successful, I am experiencing difficulties in displaying the retrieved data. Below is the code snip ...

JavaScript loop to process form submissions

Running a for loop through data retrieved from the Facebook API, my goal is to store this data in my own database for use on other websites. The issue arises during the submission process, as it seems I can only submit once. The culprit appears to be the ...

A guide to downloading a file linked to Javascript with the help of Java

I have a unique request here. I am looking for a solution using HttpUrlConnection that can interact with JavaScript directly on a webpage, instead of relying on Selenium as a workaround. Can anyone assist me with this? The webpage contains a link (hidden ...

Creating captchas seems like a mistake in reasoning to me

I am encountering an issue with my code. I created a basic newbie-level captcha using Javascript. Below is the code snippet: <!DOCTYPE html> <html> <head> <style> </style> </head> <body> <h1>T ...

Display or conceal div elements using JavaScript

Is there a way to hide certain divs when clicking on a specific div box? Clicking on the box will trigger the hiding of some application divs. See the first image below: When the boxes are hidden, the other divs will readjust in place of the current divs ...

"Convert a date string to a date object using the verbose moment date

I utilized the materialize datepicker to select a date in French format. Now I need to convert this formatted date back to a date object for use in my API. Here's how I attempted to revert the date to a standard format: moment("dimanche 30 juillet 20 ...

What is the best method for saving and retrieving a class object in a web browser's storage?

Looking for a way to create page-reload proof class instances in my Angular 2 application. Within my component's .ts file, I have defined the following classes: export class AComponent implements OnInit { foo: Foo = new Foo(); ngOnInit() { / ...

Tips for handling uncaught exceptions in Internet Explorer

In both Chrome and Firefox, it is possible to suppress exceptions, but unfortunately, this is not the case with Internet Explorer (IE). window.addEventListener("error", function errorHandler(event) { console.log("exception should be suppressed and not ...

Modifying properties within child components

Within my parent Vue Page, I have inserted a FormInput component inside my form. new.vue <b-form @submit.prevent="submit"> <FormInput :name="name"/> <b-button @click="submit">Save</b-button> <b-form> <script> i ...

Locating the body tag within an AJAX HTML response

I have been experimenting with making an ajax call to retrieve content and then appending it in a certain way. Here is the code I am working with: $(function(){ var site = $('input').val(); $.get('file.php', { site:site }, func ...

How come my date computed property does not update reactively when changes occur?

I have a Date object in my data, and I need to convert the date into a string for a date picker component in Vuetify. The initial date is being read and displayed correctly. I am able to set the date as well - when I set a code breakpoint, I can see the ...

Organize data in a table using a dropdown selection menu

My data structure looks like this: $scope.friends = [ { name:'John', phone:'555-1212', age:10 }, { name:'Mary', phone:'555-9876', age:19 }, { name:'Mike', phone:'555-4321', age:21 }, { na ...

Using w3-include-html with a relative URL path

Is there a way for me to use the same header HTML on multiple pages within subdirectories without having to duplicate the file itself? As shown in the code snippet below, the header file is located in both the current directory and parent directory. While ...

How to selectively disable options in p-dropdown using Angular Reactive Forms

Implementing PrimeNg p-dropdown in a component. <p-dropdown [options]="productRequest" formControlName="request" optionLabel="ProductName" (onChange)="someFunction('request')"> </p-dropdown> ...

What is the best way to display an HTML file in Express when utilizing React as the frontend?

As a newcomer to the world of web development, I'm facing a seemingly simple issue that is consuming much of my time. I have set up an express server to run React on the front end. To achieve this, I use webpack and bundle to parse my react app, and ...

Unable to submit with the enter key using vue-btn

I am have a common login form with a submit button at the end, currently requiring me to click the button with my mouse to submit. However, I would like to be able to simply press the enter key to submit the form. Here is the code for my button: <v-bt ...

Socket.io-powered notification system

I'm currently in the process of developing a notification system for my Events Manager Website. Every time a user is logged in and performs an action (such as creating an event), a notification about the event creation should be sent to other user ...

Discover the method of utilizing my current location to determine the distance between two points by inputting their latitude and longitude

I'm currently working on customizing my REST API to only retrieve items that fall within a specific radius. I have successfully written the code to calculate the distance between two points and filter out items outside the desired range. However, my c ...