srarfian:pagination
This is a fork of kurounin:pagination focused on the core pagination engine only.
Compatible with Meteor 1.2.1+, Meteor 2.x, and Meteor 3.x.
📦 What's included? Server-side publication (
publishPagination) and client-side subscription management (Meteor.Pagination).❌ What's NOT included? UI components (paginator buttons, page numbers, etc.). For UI, use existing libraries like
kurounin:pagination-blazeor build your own.
Features
- Incremental subscriptions. Downloads only what is needed, not the entire collection at once. Suitable for large datasets.
- Instant changes propagation. Any document changes are instantly propagated, thanks to light-weight modifications of subscription mechanism.
- Easy integration. The package works out of the box. Page changes are triggered by a single reactive dictionary variable.
- Multiple collections per page. Each Pagination instance runs independently. You can even create multiple paginations for one collection on a single page.
- Lightweight core package. This package only contains the core pagination logic (server publication + client subscription). UI components (paginator buttons/templates) need to be implemented separately or use existing libraries.
Installation
Core Package (Required)
meteor add srarfian:pagination
⚠️ Important: This package only provides the core pagination logic (server-side publication and client-side subscription management). It does NOT include UI components (paginator buttons, page numbers, etc.).
UI Components (Optional - Choose One)
Since this is a fork focused on the core pagination engine, you need to implement your own UI components or use existing libraries:
Option 1: Using kurounin's UI packages (Recommended)
For Blaze paginator:
meteor add kurounin:pagination-blaze
Usage: {{> defaultBootstrapPaginator pagination=templatePagination}}
For ReactJS paginator (Meteor 1.2):
meteor add kurounin:pagination-reactjs
For ReactJS paginator (Meteor 1.3+):
npm i react-bootstrap-pagination
Option 2: Build Your Own UI
You can create custom paginator components using the pagination instance methods:
pagination.currentPage()- get/set current pagepagination.totalPages()- get total number of pagespagination.perPage()- get/set items per page
See examples below for building custom paginators.
Usage
In your collections file (e.g. lib/collections.js):
1import { Mongo } from 'meteor/mongo'; 2 3MyCollection = new Mongo.Collection('myCollectionName');
In your publications file (e.g. server/publications.js):
1import { publishPagination } from 'meteor/srarfian:pagination'; 2 3publishPagination(MyCollection);
Optionally you can provide a set of filters on the server-side or even dynamic filters, which can not be overridden. There's also the option of providing a transformation filter function to validate the client filters (e.g. server/publications.js):
1publishPagination(MyCollection, { 2 filters: {is_published: true}, 3 dynamic_filters: function () { 4 return {user_id: this.userId}; 5 }, 6 transform_filters: function (filters, options) { 7 // called after filters & dynamic_filters 8 allowedKeys = ['_id', 'title']; 9 10 const modifiedFilters = []; 11 12 // filters is an array of the provided filters (client side filters & server side filters) 13 for (let i = 0; i < filters.length; i++) { 14 modifiedFilters[i] = _.extend( 15 _.pick(filters[i], allowedKeys), 16 {user_id: this.userId} 17 ); 18 } 19 20 return modifiedFilters; 21 }, 22 transform_options: function (filters, options) { 23 const fields = { name: 1, email: 1 } 24 if (Roles.userIsInRole(this.userId, 'admin')) { 25 fields.deleted = 1; 26 } 27 options.fields = _.extend(fields, options.fields); 28 return options; 29 } 30}); 31
For Blaze template
In your template file (e.g. client/views/mylist.html):
1<template name="myList"> 2 <div> 3 {{#if isReady}} 4 <ul> 5 {{#each documents}} 6 <li>Document #{{_id}}</li> 7 {{/each}} 8 </ul> 9 {{> defaultBootstrapPaginator pagination=templatePagination limit=10 containerClass="text-center" onClick=clickEvent}} 10 {{else}} 11 Loading... 12 {{/if}} 13 </div> 14</template>
kurounin:pagination-blaze package is needed for paginator
In your template javascript file (e.g. client/scripts/mylist.js):
1Template.myList.onCreated(function () { 2 this.pagination = new Meteor.Pagination(MyCollection, { 3 sort: { 4 _id: -1 5 } 6 }); 7}); 8 9Template.myList.onDestroyed(function () { 10 // Cleanup to prevent memory leaks 11 this.pagination.destroy(); 12}); 13 14Template.myList.helpers({ 15 isReady: function () { 16 return Template.instance().pagination.ready(); 17 }, 18 templatePagination: function () { 19 return Template.instance().pagination; 20 }, 21 documents: function () { 22 return Template.instance().pagination.getPage(); 23 }, 24 // optional helper used to return a callback that should be executed before changing the page 25 clickEvent: function() { 26 return function(e, templateInstance, clickedPage) { 27 e.preventDefault(); 28 console.log('Changing page from ', templateInstance.data.pagination.currentPage(), ' to ', clickedPage); 29 }; 30 } 31});
For ReactJS template
In your view file (e.g. client/views/mylist.jsx):
1class MyListPage extends React.Component { 2 constructor(props) { 3 super(props); 4 this.pagination = new Meteor.Pagination(MyCollection); 5 } 6 7 componentWillUnmount() { 8 // Cleanup to prevent memory leaks 9 this.pagination.destroy(); 10 } 11 12 render() { 13 // ... render logic 14 } 15}
For Meteor 1.2 kurounin:pagination-reactjs package is needed for paginator
For Meteor 1.3+ react-bootstrap-pagination npm package is needed for paginator
Demo project
For an example on how this package can be implemented check the pagination example project.
You can also checkout this example application in React created by mgscreativa.
Server Pagination settings available on init
name: set the publication name (defaults to collection name; needs to be unique, to not collide with other publications)filters: provide a set of filters on the server-side, which can not be overridden (defaults to {}, meaning no filters)dynamic_filters: provide a function which returns additional filters to be applied (this is the publication; receives no other parameters)transform_filters: provide a function which returns the modified filters object to be applied (this is the publication; receives the current filters as an array containing the client & server defined filters and options as parameters)transform_options: provide a function which returns the modified options object to be applied (this is the publication; receives the current filters as an array containing the client & server defined filters and options as parameters)countInterval: set the interval in ms at which the subscription count is updated (defaults to 10000, meaning every 10s)
Client Pagination settings available on init
name: set the subscription name (defaults to collection name; needs to be identical with the server side publication name)page: set the initial page, for example the page parameter from url (defaults to 1)perPage: set the number of documents to be fetched per page (defaults to 10)skip: set the number of documents that should be skipped when fetching a page (defaults to 0)filters: filters to be applied to the subscription (defaults to {}, meaning no filters)fields: fields to be returned (defaults to {}, meaning all fields)sort: set the sorting for retrieved documents (defaults to {_id: 1})reactive: set the subscription reactivity, allowing to only retrieve the initial results when set to false (defaults to true)debug: console logs the query and options used when performing the find (defaults to false)connection: the server connection that will manage this collection. Pass the return value of calling DDP.connect to specify a different server. (defaults to Meteor.connection)
Client Pagination available methods
currentPage([int]): get/set the current pageperPage([int]): get/set the number of documents per pageskip([int]): get/set the number of documents to skipfilters([Object]): get/set the current filtersfields([Object]): get/set the retrieved fieldssort([Object]): get/set the sorting orderdebug([boolean]): get/set the debugtotalItems(): get the total number of documentstotalPages(): get the total number of pagesready(): checks if the subscription for the current page is readyrefresh(): forcefully refreshes the subscription (useful for non-reactive subscriptions)getPage(): returns the documents for the current pagedestroy(): cleanup method to stop subscriptions and prevent memory leaks. Call this when component/template is destroyed (e.g., incomponentWillUnmountfor React oronDestroyedfor Blaze)
Blaze Paginator template
A Blaze template is provided to allow navigation through available pages:
In the template html file add the paginator
1{{> defaultBootstrapPaginator pagination=templatePagination onClick=clickEvent limit=10 containerClass="text-center"}}
Available template parameters are:
pagination: pagination instancelimit: the maximum number of page links to displaycontainerClass: optional container class for the paginatorpaginationClass: optional class for the ul element (defaults topagination)itemClass: optional class for the page links elementswrapLinks: if set to true page links will be wrapped in li elements (defaults totrue)onClick: optional callback to be called when page link is clicked (default callback runse.preventDefault())
ReactJS Paginator class
A ReactJS class is provided to allow navigation through available pages:
1<DefaultBootstrapPaginator pagination={this.pagination} limit={10} containerClass="text-center" />
Available class properties are:
pagination: pagination instancelimit: maximum number of page links to display (defaults to 10)containerClass: optional container class for the paginator
Changelog
1.2.1
- Fixed: Memory leak in server publication (
clearIntervalinstead ofclearTimeout) - Fixed: Deprecated
Meteor.Collectionreplaced withMongo.Collection - Fixed:
instanceofcheck in constructor now uses correct class name - Added:
destroy()method for proper cleanup to prevent memory leaks - Added: Division by zero protection in
totalPages()method - Updated: Meteor 2.x compatibility
Packages used as inspiration:
- alethes:pages for pagination instantiation
- aida:pagination for bootstrap paginator template