data-grid.js
* @module greppy/helper/controller/data-grid
* @author Hermann Mayer <hermann.mayer92@gmail.com>
var sqlUtils = require('sequelize').Utils;
var extend = require('extend');
* Build the filter criteria for a given request.
* @param {Object} req - Request to analyse
* @param {Object} res - Response to call on errors
* @param {Object} options - Options to use
DataGrid.prototype.buildBaseCriteria = function(req, res, options)
options.limit = options.limit || 25;
options.properties = options.properties || ['created_at'];
options.pageSizes = options.pageSizes || [10, 25, 50, 100];
options.fuzzySearch = ('undefined' !== typeof options.fuzzySearch) ? options.fuzzySearch : true;
options.softDeletion = ('undefined' !== typeof options.softDeletion) ? options.softDeletion : true;
var page = parseInt(req.query.page) || 1;
var limit = parseInt(req.query.limit) || options.limit;
var offset = (1 < page) ? ((page * limit) - limit) : 0;
var render = req.query.render || 'all';
// Render the whole page or just the partials
if ('pagination' === render) {
* Build a SQL pagination object by a sql-criteria object.
* @param {Object} sqlCriteria - Criteria object to get data from
* @param {Object} options - Options to use
* @param {Function} callback - Function to call on finish
DataGrid.prototype.buildSqlPagination = function(sqlCriteria, options, callback)
greppy.db.get(options.connection).getORM(function(orm, models) {
stripedSqlCriteria.include = sqlCriteria.include;
models[options.entity].count(stripedSqlCriteria).success(function(count) {
pageSizes : sqlCriteria.pageSizes
* Build the SQL filter criteria for a given request.
* @param {Object} req - Request to analyse
* @param {Object} res - Response to call on errors
* @param {Object} options - Options to use
DataGrid.prototype.buildSqlCriteria = function(req, res, options)
var sqlCriteria = this.buildBaseCriteria(req, res, options);
// Add includes to criteria object
sqlCriteria.include = options.include;
if (req.query.search && req.query.sprop) {
properties = options.properties;
// We don't accept any other properties
if (-1 === properties.indexOf(req.query.sprop)) {
var prefix = (options.wherePrefix || '');
var query = ' LIKE ' + sqlUtils.escape('%' + req.query.search + '%');
if ('fuzzy' == req.query.sprop) {
where = properties.join(query + ' OR ' + prefix) + query;
where = req.query.sprop + query;
where = '(' + prefix + where + ')';
if ('undefined' === typeof where) {
if ('trash' == req.query.filter) {
where += '(' + (options.wherePrefix || '') + 'deleted_at IS NOT NULL)';
where += '(' + (options.wherePrefix || '') + 'deleted_at IS NULL)';
if (req.query.order && req.query.oprop) {
properties = options.properties;
// We don't accept any other properties
if (-1 === properties.indexOf(req.query.oprop)) {
// We don't accept any other modes
if (-1 === modes.indexOf(req.query.order.toUpperCase())) {
order = req.query.oprop + ' ' + req.query.order.toUpperCase();
if ('undefined' === typeof where) {
sqlCriteria.where = (options.where ? options.where : undefined);
sqlCriteria.where = where + (options.where ? ' ' + options.where : '');
* Build a NoSQL pagination object by a NoSql-criteria object.
* @param {Object} noSqlCriteria - Criteria object to get data from
* @param {Object} options - Options to use
* @param {Function} callback - Function to call on finish
DataGrid.prototype.buildNoSqlPagination = function(noSqlCriteria, options, callback)
greppy.db.get(options.connection).getORM(function(orm, models) {
models[options.entity].count(noSqlCriteria.where, function(err, count) {
return callback && callback(err);
pageSizes : noSqlCriteria.pageSizes
* Build the NoSQL filter criteria for a given request.
* @param {Object} req - Request to analyse
* @param {Object} res - Response to call on errors
* @param {Object} options - Options to use
DataGrid.prototype.buildNoSqlCriteria = function(req, res, options)
var noSqlCriteria = this.buildBaseCriteria(req, res, options);
if (req.query.search && req.query.sprop) {
properties = options.properties;
// We don't accept any other properties
if (-1 === properties.indexOf(req.query.sprop)) {
"$regex": '.*' + req.query.search + '.*',
if ('fuzzy' == req.query.sprop) {
properties.forEach(function(property) {
if (/^(created|updated|deleted)_at$/i.test(property)) {
expression[req.query.sprop] = query;
if ('trash' == req.query.filter) {
if (req.query.order && req.query.oprop) {
properties = options.properties;
// We don't accept any other properties
if (-1 === properties.indexOf(req.query.oprop)) {
// We don't accept any other modes
if (-1 === modes.indexOf(req.query.order.toUpperCase())) {
order[req.query.oprop] = ('DESC' === req.query.order.toUpperCase()) ? -1 : 1;
// Allow extending the where condition