Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement Infinite Scrolling using Node.js, Angular.js and Firebase?

UPDATE 8:

CODE:

<% include ../partials/header %>


<script src="https://www.gstatic.com/firebasejs/3.5.2/firebase.js"></script>
<script src="https://cdn.firebase.com/libs/firebase-util/0.2.5/firebase-util.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.2/angular.js"></script>
<script src="https://cdn.firebase.com/libs/angularfire/1.1.4/angularfire.min.js"></script>

<script>


  var config = {
     info
  };

  firebase.initializeApp(config);

    var fb = firebase.database().ref("posts/fun");

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

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

        $scope.data = [];
        var _start = 0;
        var _end = 4;
        var _n = 5;

        $scope.getDataset = function() {

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

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

            });

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

        };


        $scope.getDataset()

    });

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


</script>


<div class ="containerMarginsIndex">

   <div ng-controller="ctrl">

            <div class="fun" ng-repeat="d in data">
                <h3 class="text-left">{{d.title}}</h3>
                    <div class = "postImgIndex">
                        <a href="details/{{d.id}}" target="_blank">
                            <img class= "imgIndex" ng-src="/images/uploads/{{d.image}}" >
                        </a>
                    </div> 
                <div class="postScore">{{d.upvotes - d.downvotes}} HP</div>
            </div>

    </div>

</div>

<% include ../partials/footer %>

SITUATION:

Ok, I have reworked my Firebase database architecture and changed the Firebase rules.

I am now certain the Firebase function returns a value (it is logged in the console).

But I still get the following error:

This HTML:

    <div class="fun" ng-repeat="d in data">
        <h3 class="text-left">{{d.title}}</h3>
            <div class = "postImgIndex">
                <a href="details/{{d.id}}" target="_blank">
                    <img class= "imgIndex" ng-src="/images/uploads/{{d.image}}" >
                </a>
            </div> 
        <div class="postScore">{{d.upvotes - d.downvotes}} HP</div>
    </div>

gets REPLACED by this once RENDERED:

<!-- ngRepeat: d in data --> == $0

What have I done wrong ?

like image 779
Coder1000 Avatar asked Nov 12 '16 17:11

Coder1000


Video Answer


3 Answers

It's not displaying in your view because you have nothing on the $scope and you're not using {{}} to interpolate your data. See the following changes:

Assign data to a $scope variable to be used in the view:

$scope.data = [];
var _start = 0;
var _end = 4;
var _n = 5;
var getDataset = function() {
  fb.orderByChild('time').startAt(_start).endAt(_end).limitToLast(_n).on("child_added", function(dataSnapshot) {
  $scope.data.push(dataSnapshot.val());
});

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

And your view, use ngRepeat and {{}} to interpolate:

<div class ="containerMarginsIndex">

          <div class="fun" ng-repeat="d in data">
            <h3 class="text-left">{{d.title}}</h3>
            <div class = "postImgIndex">
            <a href="details/{{post.id}}" target="_blank">
                <img class= "imgIndex" src="/images/uploads/{{post.image}}" >
            </a>
            </div> 
            <div class="postScore">({{d.upvotes - d.downvotes}}) HP</div>
        </div>

</div>
like image 168
tymeJV Avatar answered Oct 14 '22 19:10

tymeJV


Add your scroll listener within your controller. The function more does not exist indeed, however you do have a $scope.more method.

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

    // ORDERED BY TIME:
    var ref = firebase.database().ref("posts/fun");
    var scrollRef = new Firebase.util.Scroll(ref, "time");
    $scope.posts = $firebaseArray(scrollRef);
    scrollRef.scroll.next(5);

    // AS DATA APPEARS IN DATABASE ORDERED BY TIME:
    ref.once('value', function(snap) {
        $scope.rawdata = snap.val();
        $scope.$apply();
    });

    $scope.more = function() {
       scrollRef.scroll.next(5);
    };

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

Note that I am calling $scope.more within $scope.$apply so that the scope is digested at the end of the call. Indeed a JS listener on a window scroll event is out of the Angular lifecycle so we need to manually $digest the scope for Angular to update all its watchers and update the HTML. Search online about $scope.$apply if you want to learn more about it.

About your first problem

Your angular application is not started because angular is never initialized. For that you need either to load it synchronously and use the ng-app directive, or if you don't want to change anything with your code you can simply add these lines after your module and controller definition:

// Compile the whole <body> with the angular module named "app"
angular.bootstrap(document.body, ['app']);
like image 40
floribon Avatar answered Oct 14 '22 18:10

floribon


You need to include $scope.$apply() because the the scroll event executes outside Angular's context.

Also the event listener should be inside your controller so that the scoped more function is accessible.

Here's an updated fiddle:

https://jsfiddle.net/xue8odfc/2/

I'd say the problem with Angular not resolving the {{post.image}} etc. is due to incompatibilities among the libraries you are referencing. I suggest testing using the versions from the working jsfiddle:

<script src="https://cdn.firebase.com/js/client/2.0.3/firebase.js"></script>
<script src="https://cdn.firebase.com/libs/firebase-util/0.2.5/firebase-util.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.1.1/angular.min.js"></script>
<script src="https://cdn.firebase.com/libs/angularfire/1.1.4/angularfire.min.js"></script>
like image 20
K Scandrett Avatar answered Oct 14 '22 19:10

K Scandrett