javascript 44 lines · 7 steps

Building a paginated orders page in Express

An Express route reads a page number, queries a slice of orders, and renders a full pagination model for the view.

Explained by highlit
1const express = require('express');
2const router = express.Router();
3const db = require('../db');
4 
5const PER_PAGE = 20;
6 
7router.get('/orders', async (req, res, next) => {
8 try {
9 const page = Math.max(1, parseInt(req.query.page, 10) || 1);
10 const offset = (page - 1) * PER_PAGE;
11 
12 const [{ count }] = await db('orders').count({ count: '*' });
13 const totalPages = Math.max(1, Math.ceil(count / PER_PAGE));
14 
15 const orders = await db('orders')
16 .select('orders.id', 'orders.total', 'orders.status', 'orders.created_at', 'customers.name as customer')
17 .join('customers', 'customers.id', 'orders.customer_id')
18 .orderBy('orders.created_at', 'desc')
19 .limit(PER_PAGE)
20 .offset(offset);
21 
22 res.render('orders/index', {
23 title: 'Orders',
24 orders,
25 pagination: {
26 page,
27 totalPages,
28 hasPrev: page > 1,
29 hasNext: page < totalPages,
30 prevUrl: `/orders?page=${page - 1}`,
31 nextUrl: `/orders?page=${page + 1}`,
32 pages: Array.from({ length: totalPages }, (_, i) => ({
33 number: i + 1,
34 url: `/orders?page=${i + 1}`,
35 current: i + 1 === page,
36 })),
37 },
38 });
39 } catch (err) {
40 next(err);
41 }
42});
43 
44module.exports = router;
01 / 01
STEP 01

Walkthrough

Space play ←→ step click any line
Three takeaways
  1. 1Clamping and coercing user input keeps pagination math safe from bad query strings.
  2. 2Precomputing a full pagination model on the server keeps templates dumb and declarative.
  3. 3Wrapping async handlers in try/catch and forwarding to next() routes errors through Express middleware.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Building a paginated orders page in Express — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code