Infinite scroll with AngularJs and Firebase
Asked Answered
N

1

7

How do you implement infinite scroll on data that you get from firebase. So far I found an angularjs directive, that works really great but I'm having difficulty implementing it with fireable as firebase returns all data in one single request and this is not what I want.

Nimitz answered 4/4, 2014 at 16:51 Comment(2)
If there is no way to paginate data in Firebase then there's no point to an infinite scroll. But somehow I have trouble believing that there's no pagination functionality - have you searched their API documentation?Intolerable
Actually, it is exactly pagination. :) jsfiddle.net/katowulf/yumaBEnlarge
R
19

Few weeks ago, I made a JS function that allowed an infinite scrolling in my app.

First, a set of data is displayed when the user visit the website:

// Add a callback that is triggered for each message.
var n = 25; // Step size for messages display.
$(window).load(function() {
lastMessagesQuery = messagesRef.limit(n); 
lastMessagesQuery.on('child_added', function (snapshot) {
  var message = snapshot.val();
  $('<div/>').text(message.text).prependTo($('#messagesDiv'));
  $('#messagesDiv')[0].scrollTop = $('#messagesDiv')[0].scrollHeight;
});
$('#messagesDiv').fadeTo(1000, 1);
});

Then, the function that makes possible the infinite scrolling:

// Pagination.
var i = 0; // Record variable.
function moreMessages () { 
i += n; // Record pagination updates. 
moreMessagesQuery = messagesRef; // Firebase reference.
moreMessagesQuery.on('value', function (snapshot) {
  var data = snapshot.exportVal(); // Fetch all data from Firebase as an Object.
  var keys = Object.keys(data).reverse(); // Due to the Keys are ordered from the oldest to the newest, it nessesary to change its sequence in order to display Firebase data snapshots properly.
  var total_keys = Object.keys(data).length;
  var k = keys[i]; // Key from where to start counting. Be careful what Key you pick.
  if (i < total_keys) { // Stop displaying messages when it reach the last one.
    lastMessagesQuery = messagesRef.endAt(null, k).limit(n); // Messages from a Key to the oldest.
    lastMessagesQuery.on('child_added', function (snapshot) {
      var message = snapshot.val();
      $('<div/>').text(message.text).appendTo($('#messagesDiv')).hide().fadeIn(1000); // Add set of messages (from the oldest to the newest) at the end of #messagesDiv.
    });
  }  
});
}

Finally, the infinite scrolling:

// Load more messages when scroll reach the bottom.
$(window).scroll(function() { 
if (window.scrollY == document.body.scrollHeight - window.innerHeight) {
  moreMessages();
}  
}); 

It works great with small data sets. I hope this helps you to solve your problem (or gives you more ideas).


UPDATE October 2015

Firebase has growth since my original response, which means now it's pretty easy to achieve an infinite scrolling just using its Javascript API:

First, I recommend to create an Index in your Firebase. For this answer, I create this one:

{
   "rules": {
      ".read": true,
      ".write": false,
      "messages": {
         ".indexOn": "id"
      }
   }
}

Then, let's make some magic with Firebase:

// @fb: your Firebase.
// @data: messages, users, products... the dataset you want to do something with.
// @_start: min ID where you want to start fetching your data.
// @_end: max ID where you want to start fetching your data.
// @_n: Step size. In other words, how much data you want to fetch from Firebase.
var fb = new Firebase('https://<YOUR-FIREBASE-APP>.firebaseio.com/');
var data = [];
var _start = 0;
var _end = 9;
var _n = 10;
var getDataset = function() {
   fb.orderByChild('id').startAt(_start).endAt(_end).limitToLast(_n).on("child_added", function(dataSnapshot) {
      data.push(dataSnapshot.val());
   });
   _start = _start + _n;
   _end = _end + _n;
}

Finally, a better Infinite Scrolling (without jQuery):

window.addEventListener('scroll', function() {
  if (window.scrollY === document.body.scrollHeight - window.innerHeight) {
     getDataset();
  } 
});

I'm using this approach with React and it's blazing fast no matter how big your data is.

Revest answered 5/4, 2014 at 20:42 Comment(6)
Where do you add the infinite scrolling? Nothing happens for me when I scrollPseudoscope
@JohnAndrews I add it in my main JS file. If you're using React, just look at this example: github.com/heartyrobot/brands/blob/master/src/js/app.js#L56 (BTW, you need to display data in order to make things happens.)Revest
that means registering an on listener every time getDataSet() is called... is that reasonable? and it only works if you want an ascending order.Eddins
also, if a child is added to an already loaded page, your code pushes it to the end of the list instead of inserting it at its right placeEddins
You are right @antoine129, my code only works in ascending order, but that depends entirely of your requirements. You could easily reverse data Array to meet your needs... something like var _data = data.reverse() or using sort.Revest
@Revest This is an amazing implementation.I am trying to do the exact same using angular 2 with Observable, which looks like getUsers(): Observable<any> { return this.http.get(${baseUrl}.json).map((res: Response) => { this.data = res.json(); return this.data; }); } but using that I am unable to implement, typescript keeps saying there is no OrderByChild property, could you please tell me how you would do it in Angular 2. Thank youLancelle

© 2022 - 2024 — McMap. All rights reserved.