Behrouz Riahi
Behrouz Riahi

Reputation: 1791

Infinite scrolling with Meteor

I am trying to load 12 items only each time, until the user scroll all the way down and load another 12 elements

For some reason my code doesn't work. When i upload another item, i can see it in the admin panel so it is successfully uploaded but i can't see it in the normal user view. i can only view the first 12 items uploaded and it doesn't load anymore items when i scroll.

Here is my code in the client side

if (Meteor.isClient) {

    var ITEMS_INCREMENT = 12; //this one refers to the number of elements to load
    Session.setDefault('itemsLimit', ITEMS_INCREMENT);
    Deps.autorun(function() {
        Meteor.subscribe('items', Session.get('itemsLimit'));
    });

    Template.list_products.helpers({
        applications: function () {
            var limit = Session.get("itemsLimit");

            //return Products.find({}, { sort: {createdAt: -1},limit: limit }); // render latest first

            return Products.find({}, { sort: {createdAt: 1},limit: limit }); // render first first
        }
    });

    Template.list_products.moreResults = function() {
        // If, once the subscription is ready, we have less rows than we
        // asked for, we've got all the rows in the collection.
        return Products.find({}, { sort: {createdAt: -1},limit: limit });
    }

    // whenever #showMoreResults becomes visible, retrieve more results
    function showMoreVisible() {
        var threshold, target = $("#showMoreResults");
        if (!target.length) return;

        threshold = $(window).scrollTop() + $(window).height() - target.height();

        if (target.offset().top < threshold) {
            if (!target.data("visible")) {
                // console.log("target became visible (inside viewable area)");
                target.data("visible", true);
                Session.set("itemsLimit",
                    Session.get("itemsLimit") + ITEMS_INCREMENT);
            }
        } else {
            if (target.data("visible")) {
                // console.log("target became invisible (below viewable arae)");
                target.data("visible", false);
            }
        }
    }

    // The below line is to run the above func every time the user scrolls
    $(window).scroll(showMoreVisible);
}

Upvotes: 5

Views: 1979

Answers (2)

Behrouz Riahi
Behrouz Riahi

Reputation: 1791

Here how i solved it:

if(Meteor.isClient) {
  Session.set("itemsLimit", 9); // to set the limit to 9

  lastScrollTop = 0;

  $(window).scroll(function(event){
    if($(window).scrollTop() + $(window).height() > $(document).height() - 100) { // to detect scroll event
      var scrollTop = $(this).scrollTop();

      if(scrollTop > lastScrollTop){ // detect scroll down
        Session.set("itemsLimit", Session.get("itemsLimit") + 9); // when it reaches the end, add another 9 elements
      }

      lastScrollTop = scrollTop;
    }
  });
}

It works like a charm now :)

Upvotes: 4

Sapna
Sapna

Reputation: 683

You can implement it like this:

HTML File:

<template name="yourTemplateName">
   <div id="divId">
      {{#each dataArr}}
         //your view here.
      {{/each}}
   </div>
  {{#if noMoreItem}}
  <span>No more items to show</span>
  {{/if}}
</template>

JS File:

var pageNumber = new ReactiveVar(0);
var noMoreItem = new ReactiveVar(false);
var mainContainer = // Your element here example: document.getElementById('divId')
mainContainer.addEventListener('scroll', function(){
    if(mainContainer.scrollHeight - mainContainer.scrollTop === mainContainer.clientHeight) {
        getMoreItems();
    }
});
var getMoreItems = function () {
   if(pageNumber.get() < Math.floor(Counts.get('countItems')/12)) {
      pageNumber.set(Number(pageNumber.get())+1);
      Meteor.subscribe('pubName', pageNumber.get(), 12);
  } else {
     noMoreItem.set(true);
  }
}

Template.yourTemplateName.rendered = function () {
   pageNumber.set(0);
   Meteor.subscribe('pubName', pageNumber.get(), 12);
}

Template.yourTemplateName.helpers({
   'dataArr': function () {
      return CollectionName.find();
   },
  'noMoreItem': function () {
      return noMoreItem.get();
   }
})

Publication:

Meteor.publish("pubName", function (pageNumber, pageSize) {
   Counts.publish(this, 'countItems', Meteor.users.find(filter), {
      noReady: true
   });
   return CollectionName.find({}, {
      skip: pageNumber > 0 ? ((pageNumber) * pageSize) : 0,
      limit: pageSize
   })
});

Upvotes: 2

Related Questions