9

CODE:

<script>

    var app = angular.module('app', ['firebase']);

    app.controller('ctrl', function ($scope, $firebaseArray, $timeout) {


            console.log(<%=lastID%>);

            $scope.data = [];
            var _n = Math.ceil(($(window).height() - 50) / (350)) + 1;
            var _start = <%= lastID %>;
            var _end = <%= lastID %> + _n - 1;

            $scope.getDataset = function() {

                fb.orderByChild('id').startAt(_start).endAt(_end).limitToLast(_n).on("child_added", function(dataSnapshot) {

                    $scope.data.push(dataSnapshot.val());
                    $scope.$apply()
                    console.log("THE VALUE:"+$scope.data);

                });

                _start = _start + _n;
                _end = _end + _n;

            };


            $scope.getDataset();

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

    });

    // Compile the whole <body> with the angular module named "app"
    angular.bootstrap(document.body, ['app']);


</script>

SITUATION:

lastID is the ID of the last post created. They go backwards (from -1 to lastID).

This solution works perfectly except when some posts are deleted.

(Posts are ordered from latest to oldest (from lastID to -1)).

For example, if there are 16 posts, lastID = -16.

If I delete posts -13 to -5 and post -3, lastID stays at -16.

Which means that when the page loads, no posts appear after the 3 first posts (-16 to -14) are loaded and I need to scroll repeatedly down to get post -4 to appear.


QUESTION:

How can I make sure that if some posts are deleted, my Infinite Scroll script will skip the ids of the inexisting posts and just load the 3 closest posts ?


WHAT I CHECKED:

I looked at this:

Display posts in descending posted order

But I am not sure as to how I would implement those solutions inside my infinite scroll. Any ideas ?

Community
  • 1
  • 1
Coder1000
  • 4,071
  • 9
  • 35
  • 84

3 Answers3

1

If I understood you correctly, you don't have to use end. This could be achieved using startAt + limit

fb.orderByChild('id').startAt(_start).limit(n)...

And use a layout to order items descending. Using this you don't have to worry about sequence of ids if they are consecutive

UPDATE

You can do this even simpler. Just update your start with a latest value

fb.orderByChild('id').startAt(_start).limit(_n).on("child_added", function(dataSnapshot) {

    $scope.data.push(dataSnapshot.val());
    $scope.$apply()
    _start = dataSnapshot.child('id').val()
    console.log("THE VALUE:"+$scope.data);

});

In this case your _start will always hold the last id and you may not worry about deleted elements. Alternatively you may use a temporary variable to store last id value and use it in startAt

Nikolay Osaulenko
  • 1,462
  • 1
  • 12
  • 21
  • Your reasoning is sound and the three items get loaded if for example I remove -2,-3 and -5 in a list of -1 to -6. Problem is: since we removed the endAt(), I can scroll a second time and -2 and -3 are loaded again. Indeed, lastID = -6 for the first set of data, but lastID = -3 for first scroll and last ID = 0 for second scroll. – Coder1000 Dec 27 '16 at 21:17
  • I would need to get the ID of the last item loaded and set _start to that. But how can I select the last ITEM inside my firebase order function ? – Coder1000 Dec 27 '16 at 21:19
  • the _start inserted to startAt will get your last loaded post from the previous query... that sucks :( – m1crdy Jan 19 '17 at 21:42
1

Basically all data saved in Firebase is ordered chronologically, since the auto-generated id for each record is based on the timestamp. Hence you don't need to order your values. Just make sure you are adding a new id in the key value pair being saved in Firebase.

In case you want to reverse the order of the list (making the most recent records appear at the top), you will need to reverse the list after reading it.

EDIT

If you want to get the position of your record in the database, you can use something similar to the following:

var ref = new Firebase("https://dinosaur-facts.firebaseio.com/dinosaurs");
ref.orderByKey().on("child_added", function(snapshot) {
  console.log(snapshot.key() + " was " + snapshot.val().height + " meters tall");
});

You can find more information about ordering here.

Michele La Ferla
  • 6,775
  • 11
  • 53
  • 79
  • I understand your reasoning and I had thought about it, but the answers using this solution use more code than the one I am currently using. I don't see much of a benefit except not having to store additional IDs inside my posts in the database. Or is there some important benefit to this approach I don't know about ? – Coder1000 Dec 29 '16 at 10:57
  • he fact that you don't need to store the ids because these are automatically generated is already a plus. All you need to do is add the following line of code when inserting a record: `var newPostRef = postsRef.push();` This will automatically generate an id base one your timestamp at the moment. – Michele La Ferla Dec 29 '16 at 12:58
  • I know ^^. But is that really the only advantage to this solution ? – Coder1000 Dec 29 '16 at 14:19
  • But with the IDs, I have the advantage to know which post was the nth post :) Which is good for marketing events ! – Coder1000 Dec 29 '16 at 20:00
  • You are not using the key, you are using an attribute just like me in your code. – Coder1000 Dec 30 '16 at 10:39
1

startAt and limitToFirst can be used to retrieve next posts.

Just tell firebase to start after id of last loaded post (start + 1 in this case), and deleted id will be skipped automatically.

var itemsPerScroll = 1;
$scope.getDataset = function() {
  var start = $scope.data.slice(-1)[0].id
  fb.orderByChild('id').startAt(start + 1).limitToFirst(itemsPerScroll)
  .on("child_added", function(dataSnapshot) {
    $scope.data.push(dataSnapshot.val());
    $scope.$apply()
  })
}
DarkKnight
  • 5,651
  • 2
  • 24
  • 36