Change your publication to accept a parameter called pageNumber
like this
Meteor.publish('posts', function (pageNumber) {
var numberOfRecordsPerPage = 10;
var skipRecords = numberOfRecordsPerPage * (pageNumber - 1);
return Post.find({
"user_id": user_id
}, {
sort: { 'cDate.timestamp': -1 }
skip: skipRecords,
limit: numberOfRecordsPerPage
});
});
On client side, I didn't work with angular-meteor much. You can create a pageNumber
property under your current scope using this.pageNumber
or $scope.pageNumber
. Update this pageNumber
variable whenever your pagination page is clicked. Whenever this variable is changed, subscribe using the current page number.
If it is using standard blaze template, I would do it using a reactive var or session var in an autorun
like this.
In template html:
<template name="postsTemplate">
<ul>
<!-- you would want to do this list based on total number of records -->
<li class="pagination" data-value="1">1</li>
<li class="pagination" data-value="2">2</li>
<li class="pagination" data-value="3">3</li>
</ul>
</template>
In template js:
Template.postsTemplate.created = function () {
var template = this;
Session.setDefault('paginationPage', 1);
template.autorun(function () {
var pageNumber = Session.get('paginationPage');
Meteor.subscribe('posts', pageNumber);
});
}
Template.postsTemplate.events(function () {
'click .pagination': function (ev, template) {
var target = $(ev.target);
var pageNumber = target.attr('data-value');
Session.set('paginationPage', pageNumber);
}
});
This way, you will have a maximum of 10 records at any point in time on the client, so it will not crash the browser. You might also want to limit the fields that you send to client using something like this
Meteor.publish('posts', function (pageNumber) {
var numberOfRecordsPerPage = 10;
var skipRecords = numberOfRecordsPerPage * (pageNumber - 1);
return Post.find({
"user_id": user_id
}, {
sort: { 'cDate.timestamp': -1 }
skip: skipRecords,
limit: numberOfRecordsPerPage,
fields: {'message': 1, 'createdBy': 1, 'createdDate': 1 } //The properties inside each document of the posts collection.
});
});
And finally you will need the total number of records in posts collection on client side, to show the pagination links. You can do it using a different publication and using the observeChanges
concept as mentioned in the official documentation here
// server: publish the current size of a collection
Meteor.publish("posts-count", function () {
var self = this;
var count = 0;
var initializing = true;
// observeChanges only returns after the initial `added` callbacks
// have run. Until then, we don't want to send a lot of
// `self.changed()` messages - hence tracking the
// `initializing` state.
var handle = Posts.find({}).observeChanges({
added: function (id) {
count++;
if (!initializing)
self.changed("postsCount", 1, {count: count});
},
removed: function (id) {
count--;
self.changed("postsCount", 1, {count: count});
}
// don't care about changed
});
// Instead, we'll send one `self.added()` message right after
// observeChanges has returned, and mark the subscription as
// ready.
initializing = false;
self.added("postsCount", 1, {count: count});
self.ready();
// Stop observing the cursor when client unsubs.
// Stopping a subscription automatically takes
// care of sending the client any removed messages.
self.onStop(function () {
handle.stop();
});
});
// client: declare collection to hold count object
PostsCount = new Mongo.Collection("postsCount");
// to get the total number of records and total number of pages
var doc = PostsCount.findOne(); //since we only publish one record with "d == 1", we don't need use query selectors
var count = 0, totalPages = 0;
if (doc) {
count = doc.count;
totalPages = Math.ceil(count / 10); //since page number cannot be floating point numbers..
}
Hope this helps.
db.Posts.ensureIndex({"cDate.timestamp": 1})
– Mcburneysort
line. You can try this suggestion #28732139 to make sure the query is using index. If it still doesn't solve the problem then sorry I also don't have idea. – McburneyMeteor.methods({ postsCount: function () { return Posts.find({}, { fields: { _id: 1 } }).count(); } })
. – Waddlefind
. – Robalofind
afterwards, you won't trigger a repeated and unnecessary sorting of the collection. At least that worked on the reproduction repo provided in the issue. But I agree that you should also consider publishing fewer documents. – Robalo