/Pidgeot

🐦Promise based mongoose configurable server-side paginator.

Primary LanguageJavaScript

Promise based express-mongoose configurable server-side paginator


/**
 * song_model.js
 **/
 
// create mongoose schema & model
const mongoose = require('mongoose');
const {Schema} = mongoose;

const songSchema = new Schema({
	name: String,
	artist: String,
	duration: Number
});

module.exports = mongoose.model('Song', songSchema);

/**
 * app.js
 */
 
const app = require('express')();
const Pidgeot = require('pidgeot');
const Song = require('./song_model');

app.get('/', (req, res) => {
    // initialize paginator instance
	const Paginator = Pidgeot({
		model: Song, 
		page: req.query.page, 
		query: {
			duration: {
				$gt: 200,
				$lte: 50
			}
		}, 
		limit: 20, 
		select: '-_id',
		sort: 'name', 
		fields: {
			collection: 'songs'
		}
	});

	// paginage
	Paginator.paginate()
	.then(data => {
		const {page, records, prev_page, next_page, num_records, num_pages} = data;
		console.log(`Page: ${page}`); // page given or 1
		console.log(`Songs: ${JSON.stringify(records)}`); // songs array
		console.log(`Prev: ${prev_page}`); // /?page={prev_page}&collection=songs
		console.log(`Next: ${next_page}`); // /?page={next_page}&collection=songs
		console.log(`Songs Count: ${num_records}`); // number of records returned 
		console.log(`Page Count: ${num_pages}`); // total number of pages
		// render template passing data
		res.render('songs_template.html', {
			page, 
			records, 
			prev_page, 
			next_page, 
			num_records, 
			num_pages
		});
	}).catch(err => {
		console.log(err.message);
		res.render('error_template.html', {message: 'Error.'});
	});
});

app.listen(8000);

Class attributes:

{
    model  :  // Mongoose model (required),
    path   :  // Route path (default '/'),
    page   :  // What page to paginate to (default 1),
    query  :  // DB query to filter records by (default {}),
    limit  :  // How many records should be shown on a page (default 50),
    select :  // Which model fields to select,
    sort   :  // How to sort the returned records (default null),
    lean   :  // Should records data return as lean array,
    fields :  // External query params to include (default {})
}

For fun, lets render a simple nunjucks template:

/**
 * app.js
 */
 
const app = require('express')();
const nunjucks = require('nunjucks');
const Pidgeot = require('pidgeot');
const Song = require('./song_model');

// config nunjucks
nunjucks.configure('views', {
	autoSpace: true,
	express: app,
	watch: true
});

// index route
app.get('/', (req, res) => {

    // initialize paginator instance
	const Paginator = Pidgeot({
		model: Song,
		page: req.query.page,
		query: {
			duration: {
				$gt: 200,
				$lte: 50
			}
		},
		limit: 20,
		select: '-_id',
		sort: 'name',
		fields: {
			collection: 'songs'
		}
	});

	// paginate (promise returned)
	Paginator.paginate()
        .then(data => {
            const {page, records, prev_page, next_page, num_records, num_pages} = data;
            // render template passing data
            res.render('songs_template.html', {
                page,
                records,
                prev_page,
                next_page,
                num_records,
                num_pages
            });
        }).catch(err => {
            console.log(err.message);
            res.render('error_template.html', {message: 'Error.'});
        });

});

app.listen(8000);
{% if records.length > 0 %}
<table class="table table-striped">
    <thead>
        <tr>
            <td>#</th>
            <td>Name</td>
            <td>Artist</td>
            <td>Duration</td>
        </tr>
    </thead>
    <tbody>
    {% for record in records %}
        <tr class="records">
            <td>{{ loop.index }}.</td>
            <td>{{ record.name }}</td>
            <td>{{ record.artist }}</td>
            <td>{{ record.duration }}</td>
        </tr>
    {% endfor %}
    </tbody>
</table>
{% endif %}

<!-- pagination -->
{% if num_pages > 1 %}
<nav aria-label="Page navigation">
    <ul class="pager">
        {% if page > 1 %}
        <li class="previous">
            <a href="{{ prev_page }}"><span aria-hidden="true">&larr;</span> Prev</a>
        </li>
        {% endif %}
        {% if page < num_pages %}
        <li class="next">
            <a href="{{ next_page }}">Next <span aria-hidden="true">&rarr;</span></a>
        </li>
        {% endif %}
    </ul>
</nav>
{% endif %}

###Install on npm:

npm install pidgeot --save

View on npm

Pidgeot