This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// articles per page | |
var limit = 10; | |
// pagination middleware function sets some | |
// local view variables that any view can use | |
function pagination(req, res, next) { | |
var page = parseInt(req.params.page) || 1, | |
num = page * limit; | |
db.articles.count(function(err, total) { | |
res.local("total", total); | |
res.local("pages", Math.ceil(total / limit)); | |
res.local("page", page); | |
if (num < total) res.local("prev", true); | |
if (num > limit) res.local("next", true); | |
next(); | |
}); | |
} | |
// a few sample routes using the pagination middleware | |
// both of them use the same view, which is enhanced | |
// by the local variables setup in the pagination function | |
app.get('/', pagination, function(req, res) { | |
db.logs.update({}, {$inc:{count:1}}); | |
db.articles.find({}, {'snippet':1,'images':1,'date':1,'title':1}, {limit:limit, sort: [['date','desc']]}, function(err, cursor) { | |
cursor.toArray(function(err, articles) { | |
res.render('home.html', { | |
articles: articles | |
}); | |
}); | |
}); | |
}); | |
// this route helps us view paginated pages, | |
// but thanks to the middleware, doesn't have | |
// to do anything fancy before rendering its view | |
app.get('/pages/:page', pagination, function(req, res) { | |
var page = req.params.page || 1 | |
db.articles.find({}, {'snippet':1,'images':1,'date':1,'title':1}, {skip: (page - 1) * limit, limit: limit, sort: [['date','desc']]}, function(err, cursor) { | |
cursor.toArray(function(err, articles) { | |
res.render('home.html', { | |
articles: articles | |
}); | |
}); | |
}); | |
}); |
Here is a partial using EJS syntax that will display some previous / next arrows wherever you choose to place them. Notice I'm using locals.prev and locals.next here, which works, becuse I'm not sure those variables will even exist. In these cases you access them as properties off of the locals object in the view, which means you don't have to do this if (typeof prev !== "undefined" && prev), which is a little more verbose if you ask me:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<nav class="pagination"> | |
<% if (locals.prev) { %> | |
<a href="/pages/<%= (page + 1) %>">Previous</a> | |
<% } %> | |
<% if (locals.next) { %> | |
<a href="/pages/<%= (page - 1) %>">Next</a> | |
<% } %> | |
</nav> |
I liked how easy the middleware approach was over having specific pagination logic in each route that used pagination. Express is fantastic for letting me send in multiple functions that I can chain together by calling next(). In this example, without using the middleware I would have had to wrap each paginated function in the count() database call, which would give me an un-neccessarily long callback chain. I prefer the simple middleware approach allowed by express.