5

I'm using firebase to save posts that have the following data:

createdAt: "Sun Apr 03 2016 18:32:46 GMT-0300 (BRT)"

What I'm trying to achieve is to get the most recent posts first and then load the older ones while the user scrolls down.

With posts retrieved using ngInfiniteScroll I'm being able to order desc using <div ng-repeat="post in posts | orderBy:'-createdAt'"> but ngInfiniteScroll keep returning the old posts first. I'm ordering but i'm ordering the older ones.

I already tried using the same logic ("-createdAt") in ngInfiniteScroll but it was not effective.


My js is pretty much this:

  var baseRef = new Firebase(FBURL).child("posts");
  var scrollRef = new Firebase.util.Scroll(baseRef, "createdAt");
  $scope.posts = $firebaseArray(scrollRef);
  $scope.posts.scroll = scrollRef.scroll;

Security and rules:

"posts": {
          ".read": true,
          ".indexOn": "createdAt",
          "$post": {
            ".read": true,
            ".write": true,
            "$other": {
               ".validate": true
            }
         }
      }
adolfosrs
  • 8,626
  • 5
  • 36
  • 65
  • I think your problem is, that you're ordering by date as string and not as Date object. Look at this answer: http://stackoverflow.com/a/25306447/752142. – illagrenan Apr 04 '16 at 17:57
  • @illagrenan My orderBy is working fine... Or are you saying that changing it to Date the ngInfiniteScroll will recognize the `"-createdAt"`? – adolfosrs Apr 04 '16 at 18:23
  • So your items are ordered correctly if you just print them without ngInfiniteScroll using simple ngRepeat? And if you use `infinite-scroll='someService.nextPage()'` items are not ordered? Am I correct? Simple solution could be: retrieve items from API, order them in your service/controller and then return ordered data from `infinite-scroll='myMethod()'`. – illagrenan Apr 04 '16 at 19:32
  • Right. Today it orders the data sets retrived with ngInfiniteScroll but they are the older sets first. I want to take new sets first and thats what I expect from ngInfiniteScroll.... If I understood you solution that is take all posts first and order them doesnt make any sense since I am trying to achieve better performance with ngInfiniteScroll. – adolfosrs Apr 04 '16 at 19:43
  • I am not that familiar with firebase, however, using ngInfiniteScroll loads remote data. So if you want it to be in a specific order you need to specify that within the firebase query. Some quick searches lead me to `orderByChild` method. Also from what I found, Firebase does not have a date type since it is JSON. You will want to set your `createdAt` to a primitive type that represents the date (`createdAt: date.getTime()`). Then I think you can do something like `ref.orderByChild("-createdAt")`. – Justin Ober Apr 07 '16 at 00:12
  • I am not a Firebase pro by any means but I think my last comment will at least give you a place to start. Hope it helps. – Justin Ober Apr 07 '16 at 00:13

2 Answers2

2

Looks like you found your solution but you were on the right track piping with the orderBy but just try tweaking it a little. Try using orderBy:'+':true", where orderBy this says you want to order it by something and the +:true says order it where anything new is on top, where -:true would say order new content on the bottom. But you can look the angular docs for it here. So if where handling it on the HTML side it would look something like this ng-repeat="post in posts| orderBy:'+':true" or:

    <div ng-repeat="post in posts| orderBy:'+':true">
           [....post info here]
      </div>

But give that a try, hope it helps.

garrettmac
  • 7,610
  • 1
  • 36
  • 53
  • What about more details on how your solution resolves the problem? – adolfosrs Apr 12 '16 at 21:24
  • And where is it passing that i want to order by the createdAt desc? – adolfosrs Apr 12 '16 at 22:04
  • Firebase adds new posts for you already in order by the time they where created. You'll notice when you add any new post to your firebase array its adding to the bottom of the stack. So when you're populated `$scope.posts` like you're doing here `$scope.posts = $firebaseArray(scrollRef);` firebase is pushing them on your `$scope.posts` variable in a stake in the same order. – garrettmac Apr 13 '16 at 01:03
  • even if a smaller post loads a few milliseconds into `$scope.posts` before a larger one, it will still place the larger one before, in order. I cannot say the same (because I haven't tried it) if you are saving them on firebase ends like an object with a path other than their pre-generated strings (like `-KFC4qa-dn3r`) but the way you're doing it I think is fine too, I don't think it's an "ugly workaround" although maybe redundant cuz it's already handle for you by firebase but now with your timestamp you could use somthing like https://github.com/wildlyinaccurate/angular-relative-date – garrettmac Apr 13 '16 at 01:29
1

After looking a little deeper at the available documentations I could find an ugly workaround here.

It is basically to use a negative timestamp and retrieve the createdAt normally (ascending).

So when saving the data I'm doing the following:

{
  createdAt: Firebase.ServerValue.TIMESTAMP,
  createdAtDesc: 0 - Date.now()
}

Still looking for a better solution.

adolfosrs
  • 8,626
  • 5
  • 36
  • 65