ParamQuery Grid Pro Tutorial

A Word about its design

ParamQuery Pro is mostly written in plain javascript which helps it to be used with any framework like Angular, React, Vue or plain javascript or jQuery. However some parts are written in jQuery & jQueryUI to leverage the jQueryUI components like datepicker, Autocomplete, Drag n Drop, position API, etc. If you are using it with modern frameworks, you don't need to learn jQuery/ jQueryUI as ParamQuery abstracts the jQueryUI API.

ParamQuery Pro is composed of various components like Treegrid, Spreadsheet, Pivot, etc which are combined into a single file/module for ease of use.

ParamQuery Pro keeps its data and view separate (literally). It has two display rendering modes:

  • Virtual mode: only the rows and columns which fit in its scrollable viewport are rendered. Typically it means that only 20-30 rows are rendered out of thousands or even million of rows and only 10 - 12 columns are rendered out of hundreds or thousands of columns at a time depending upon the scrollbar positions in the grid. It empowers grid to display unlimited rows and columns and this is the default mode of rendering in grid.
  • Non virtual mode: All the rows and columns are rendered in the viewport. It can be enabled by setting values of options virtualX, virtualY to false.

Grid refreshes its view ( and refresh event is fired ) whenever the following takes place:

  • View is scrolled either horizontally or vertically. Cells, rows moving outside the viewport are removed from DOM and new cells, rows brought in the viewport are rendered. Applicable to virtual mode.
  • Any paging event. ( virtual & non-virtual mode )
  • Any sorting event. ( virtual & non-virtual mode )
  • Any resize event. ( virtual & non-virtual mode )
  • refresh(), refreshView() or refreshDataAndView() is invoked. ( virtual & non-virtual mode )

ParamQuery Grid stores data for both local & remote requests in which is a 2 dimensional array or JSON (array of key/value paired objects). It refreshes its local copy of data for remote requests whenever the following takes place:

  • Remote paging.
  • Remote sorting.
  • Remote filtering.
  • refreshDataAndView() is invoked. can be manipulated directly for both local and remote requests.
refreshDataAndView() is invoked usually after direct manipulation of dataModel properties to put the data and view in sync. refresh() is invoked usually after modification of the grid DOM.

ParamQuery Pro includes 2 independent jQueryUI widgets/components : pqPager and pqSelect. pqPager has class pq-pager, hence reference to pqPager inside the grid can be obtained using $( ".pq-pager", $grid ).pqPager().

Syntax to obtain reference to pager is easier while working directly with javascript instances.

            var pager = grid.pager(); //js instance of pager

Include Files

To use ParamQuery Grid pro ( without npm ), first of all include these files in the header section of the web page depending upon jQueryUI or bootstrap theme.

Note: Any version of jQuery can be used but jQueryUI version should be >= 1.11.4

To use it with npm please skip to next section.


<!--jQuery dependency, any stable version of jQuery-->    
    <script src="[email protected]/dist/jquery.js"></script>    

<!--jQueryUI version >= 1.11.4 only -->
    <link rel="stylesheet" href="" />
    <script src=""></script>

<!--ParamQuery Grid css files-->
    <link rel="stylesheet" href="path to pqgrid.(min/dev).css" />    

    <!--add pqgrid.ui.css for jQueryUI theme support-->
    <link rel="stylesheet" href="path to pqgrid.ui.(min/dev).css" />

    <!--ParamQuery Grid custom theme e.g., office, bootstrap, rosy, chocolate, etc (optional)-->
    <link rel="stylesheet" href="path to custom theme pqgrid.css" />

<!--ParamQuery Grid js files-->
    <script type="text/javascript" src="path to pqgrid.(min/dev).js" ></script>   

    <!--ParamQuery Grid localization file (necessary since v5.2.0)-->
    <script src="localize/pq-localize-xx.js"></script>

<!--Include pqTouch file to provide support for touch devices (optional)-->
    <script type="text/javascript" src="path to pqtouch.min.js" ></script>   

<!--Include jsZip file to support xlsx and zip export (optional)-->
    <script type="text/javascript" src="path to jsZip.js" ></script>   

<!--Include jquery.resize to support auto height of detail views in hierarchy (optional)-->
    <script type="text/javascript" src="path to jquery.resize.js" ></script>   

Bootstrap: ( for v3.2.0 of pqGrid only )

<!--jQuery dependencies-->
    <link rel="stylesheet" href="" />
    <script src="[email protected]/dist/jquery.js"></script>    
    <script src=""></script>

<!--Bootstrap dependencies-->
    <link rel="stylesheet" href="" />

<!--ParamQuery Grid css files-->
    <link rel="stylesheet" href="path to pqgrid.(min/dev).css" />    

    <!--add pqgrid.bootstrap.css for bootstrap related classes-->
    <link rel="stylesheet" href="path to pqgrid.bootstrap.(min/dev).css" />

<!--ParamQuery Grid js files-->
    <script type="text/javascript" src="path to pqgrid.(min/dev).js" ></script>   

<!--Include Touch Punch file to provide support for touch devices (optional)-->
    <script type="text/javascript" src="path to touch-punch.min.js" ></script>   

As of v3.3.0, there is no dependency of bootstrap theme on bootstrap framework. Bootstrap theme can be used similar to any other custom theme by just including the single bootstrap custom theme css file.

jQuery, jQueryui dependency files can either point to CDN repositories (recommended) or they can point to the files kept on server locally.

For touch support in touch devices, include pqtouch.min.js file from the ParamQuery Pro SDK for versions >= v6.0.0.

The files can be reordered depending upon your requirements but pq files should be included after jQuery dependencies.

NPM Package

Evaluation version of pqgrid can be installed though a nodejs package manager e.g, npm or yarn.

npm i pqgrid

Commercial or OEM version pqgrid can be installed by using it as a local package and adding the local file system path to it in the package.json file in your project manually.

pqgrid has following peer dependencies which can also be installed through a package manager.


Dependencies are kept as peer dependencies for efficiency, though you can make them private dependencies by editing package.json file inside pqgrid package if there is any version conflict with any other package. e.g, pqgrid is dependent upon version 2.5 of jsZip and if there is any other package in your project with peer dependency on jsZip any other version, then you can make jsZip a private dependency either in pqgrid or that other package.

pqgrid exports pq module which is imported into your application by

import pq from 'pqgrid';

At least one localization is mandatory which is imported by

import 'pqgrid/localize/pq-localize-en.js';

All css files for pqgrid and dependencies are included in styles.css ( for Angular ) using @import

/* Add application styles & imports to this file! */
@import '~jquery-ui-pack/jquery-ui.css';
@import '~jquery-ui-pack/jquery-ui.structure.css';

@import '~jquery-ui-pack/jquery-ui.theme.css';

@import '~pqgrid/pqgrid.min.css';
@import '~pqgrid/pqgrid.ui.min.css';
@import '~pqgrid/themes/steelblue/pqgrid.css';

Create First ParamQuery Grid

Note: Angular, React and Vue users may skip this topic.

Within the jQuery ready function, initialize the grid as $( ".selector" ).pqGrid( obj ); where obj is a PlainObject passed to the pqGrid constructor function.

obj provides information about width, height, columns information, data, location and type of data, etc.

colModel and dataModel are the 2 main keys of information in the obj.

As their names indicate, the main role of dataModel is to provide data and data related information to the grid whereas colModel provides information specific to the columns i.e titles, widths, data type (used for sorting), etc. Please check API section to see the comprehensive list of options which can be used in obj, dataModel and colModel.


    //JSON data (array of objects) can be defined locally 
    //or might be a response from an AJAX call from web server/service.
    var data = [
        { rank: 1, company: 'Exxon Mobil', revenues: 339938.0, profits: 36130.0 },
        { rank: 2, company: 'Wal-Mart Stores', revenues: 315654.0, profits: 11231.0 },
        { rank: 3, company: 'Royal Dutch Shell', revenues: 306731.0, profits: 25311.0 },
        { rank: 4, company: 'BP', revenues: 267600.0, profits: 22341.0 },
        { rank: 5, company: 'General Motors', revenues: 192604.0, profits: -10567.0 },
        { rank: 6, company: 'Chevron', revenues: 189481.0, profits: 14099.0 },
        { rank: 7, company: 'DaimlerChrysler', revenues: 186106.3, profits: 3536.3 },
        { rank: 8, company: 'Toyota Motor', revenues: 185805.0, profits: 12119.6 },
        { rank: 9, company: 'Ford Motor', revenues: 177210.0, profits: 2024.0 },
        { rank: 10, company: 'ConocoPhillips', revenues: 166683.0, profits: 13529.0 },
        { rank: 11, company: 'General Electric', revenues: 157153.0, profits: 16353.0 },
        { rank: 12, company: 'Total', revenues: 152360.7, profits: 15250.0 },
        { rank: 13, company: 'ING Group', revenues: 138235.3, profits: 8958.9 },
        { rank: 14, company: 'Citigroup', revenues: 131045.0, profits: 24589.0 },
        { rank: 15, company: 'AXA', revenues: 129839.2, profits: 5186.5 },
        { rank: 16, company: 'Allianz', revenues: 121406.0, profits: 5442.4 },
        { rank: 17, company: 'Volkswagen', revenues: 118376.6, profits: 1391.7 },
        { rank: 18, company: 'Fortis', revenues: 112351.4, profits: 4896.3 },
        { rank: 19, company: 'Crédit Agricole', revenues: 110764.6, profits: 7434.3 },
        { rank: 20, company: 'American Intl. Group', revenues: 108905.0, profits: 10477.0 }
    //array of columns.
    var colModel = [
            title: "Rank", //title of column. 
            width: 100, //initial width of column
            dataType: "integer", //data type of column
            dataIndx: "rank" //should match one of the keys in row data.
            title: "Company", 
            width: 200, 
            dataType: "string", 
            dataIndx: "company" 
            title: "Revenues ($ millions)", 
            width: 150, 
            dataType: "float", 
            align: "right", 
            dataIndx: "revenues" 
            title: "Profits ($ millions)", 
            width: 150, 
            dataType: "float", 
            align: "right", 
            dataIndx: "profits" 

    //main object to be passed to pqGrid constructor.    
    var obj = {
        width: 700, //width of grid
        height: 400, //height of grid
        colModel: colModel,
        dataModel: {data: data}
    $("#grid_json").pqGrid( obj ); 

    pq.grid("#grid_json", obj );  //since version 3.2.0

In the body tag define the div tag/tags which act as placeholders for the grid.

<div id="grid_json"></div>

Create First Angular Grid

It's assumed that you have installed nodejs, npm or yarn, VSCode on your system and you are bit familiar with online code sharing platform Stackblitz.

pqGrid is written in pure javascript and has no internal dependency on Angular API; it's compatible with all Angular versions and is immune to any breaking changes w.r.t different Angular versions.

  • First choose any of the Angular example created with Stackblitz from demos section.
  • Click on the download icon in the Stackblitz editor.
  • Extract all files into a folder on your system.
  • Open a command prompt in the same folder.
  • Enter npm install or yarn
  • Enter ng serve or npm run ng serve
  • Enter the url localhost:4200 (as mentioned in message of your command window) in your browser.
  • Open project folder in VSCode to explore / experiment with the example.
  • If you face any issue during development in your project, then share a stackblitz of your issue.

Create First React Grid

It's assumed that you have installed nodejs, npm or yarn, VSCode on your system and you are bit familiar with online code sharing platform Stackblitz.

pqGrid is written in pure javascript and has no internal dependency on React API; it's compatible with all React versions and is immune to any breaking changes w.r.t different React versions.

  • First choose any of the React example created with Stackblitz from demos section.
  • Click on the download icon in the Stackblitz editor.
  • Extract all files into a folder on your system.
  • Open a command prompt in the same folder.
  • Enter npm install or yarn in the command prompt
  • Enter npm start in command prompt
  • Enter the url localhost:4200 (as mentioned in message of your command window) in your browser.
  • Open project folder in VSCode to explore / experiment with the example.
  • If you face any issue during development in your project, then share a stackblitz of your issue.


pqgrid supports RTL languages / layout by following steps:
  • add dir="rtl" attribute to the grid container div or any parent ( preferably body element ).
  • use pqgrid.x.rtl.y.css instead of normal pqgrid.x.y.css variant of all pqgrid stylesheets.

How to load data

There exist a number of ways to load data in pqGrid which are based on open standards & RESTful architecture. At a top level, these can be categorized into 2 cases depending upon value of dataModel.location.

Case I: dataModel.location = 'local'

When dataModel.location is local, data can be assigned directly to the grid i.e., $grid.pqGrid( 'option', '', data); where data is in format of array of rows. dataModel.location = 'local' doesn't necessarily mean local data. The data can reside locally in the browser within script tags or could be fetched from remote web server / service using synchronous or asynchronous AJAX calls. Assignment of data to grid is usually followed by a call to refreshDataAndView() in order to process and render data in the grid.

Remote paging, remote sorting and remote filtering can't be used when dataModel.location is local.

Case II: dataModel.location = 'remote'

When dataModel.location is remote, grid loads data on its own from remote location. There is no need to manually make an AJAX call and assign data to dataModel. refreshDataAndView() is called automatically by the grid whenever reload / refresh of data from remote server is required. In this case number of options have to be provided to pqGrid i.e., dataModel.url / dataModel.getUrl(), dataModel.getData(), dataModel.dataType, dataModel.method etc.

When dataModel.url is provided, grid constructs the query strings ( for GET requests ) or POST data on its own and send fields to the remote server at the specified url. The fields send by grid have prefix "pq_" for easy identification e.g., pq_curpage, pq_rpp, etc. Complete list of the name of parameters is provided in the next section. Own custom parameters can be added to the fields send by grid to the server with dataModel.postData and dataModel.postDataOnce options.

If full control is required to construct own query strings / POST data sent to server, it can be done with dataModel.getUrl() callback, though it's rarely required.

dataModel.getData() callback is called by the grid when remote data has arrived and ready to be processed by the grid. In this callback useful bits of data can be picked or incoming data can be transformed to make it suitable for grid consumption.

Remote as well as local paging, sorting and filtering can be used when dataModel.location is remote.

Remote requests

For remote paging, filtering & sorting, the grid sends the following fields of information to the server as GET or POST requests. Remote paging, filtering & sorting can be combined with each other.

TypeRequest variables
Name Value
Paging pq_datatype dataModel.dataType
pq_curpage pageModel.curPage
pq_rpp pageModel.rPP
Sorting pq_datatype dataModel.dataType
pq_sort sortModel.sorter e.g.,
pq_sort: [{"dataIndx":"ShipCountry","dir":"up"}, {"dataIndx":"ContactName","dir":"down"}]
Filtering pq_datatype dataModel.dataType
pq_filter Object variable having fields named "mode" and "data". The value of "mode" is taken from filterModel.mode and "data" is an array of objects constructed from individual column.filter e.g.,
pq_filter: { "mode": "AND", "data": [{"dataIndx":"ShipCountry","value":"fr","condition":"begin"}, {"dataIndx":"ContactName","value":"pa","condition":"begin"}]}

By default the fields are serialized to string with JSON.stringify before sending it to the server. Serialization of client requests is not required and is incompatible with some server side environments like PHP and it can be turned off by setting stringify option of pqGrid to false. As a side note, turning serialization on/off for different server environments holds true also for remote requests made during batch editing and auto save use cases.

Using jQueryUI themes

Any jQueryUI theme can be used by replacing base with the name of desired theme in the above lists of jQuery dependencies. The following is a list of ready to use 24 jQueryUI themes:

  • base
  • black-tie
  • blitzer
  • cupertino
  • dark-hive
  • dot-luv
  • eggplant
  • excite-bike
  • hot-sneaks
  • humanity
  • le-frog
  • mint-choc
  • overcast
  • pepper-grinder
  • redmond
  • south-street
  • start
  • smoothness
  • sunny
  • swanky-purse
  • trontastic
  • ui-darkness
  • ui-lightness
  • vader

For example to use Redmond theme, include the below file (if pointing to CDN repositories):
<link rel="stylesheet" 
    href="<version>/themes/redmond/jquery-ui.css" />
instead of
<link rel="stylesheet" 
    href="" />
To create your own custom theme or even to customize any of the above themes, visit here

Using jQueryUI and custom icons

Icons are used at many places in the grid e.g. in toolbar, pager, grouping icons, etc. ParamQuery Grid is jQuery theme ready and hence relies upon jQueryUI icons. Reference to a list of all jQuery icons can be obtained from and icon class names can be gathered by hovering mouse over the icons. The icon class names can be used in API of the grid.

If jQueryui icons don't satisfy your taste or need, you can create your own icons of dimensions 16px x 16px, use them in CSS classes and assign those class names to applicable parameters in API of the grid.

Use with Bootstrap

There is a conflict between jQueryUI button & tooltip with bootstrap due to same plugin names. To avoid conflict and use jQueryUI button and toolbar, the following lines of js should be added immediately after boostrap js file is included.

$.fn.bootstrapBtn = $.fn.button.noConflict();
$.fn.bootstrapTooltip = $.fn.tooltip.noConflict();            

Use with Typescript

pqGrid provides type definition file named pqgrid.d.ts in the SDK to support development with typescript.

Here are the steps to add typescript support for a project in VSCODE editor. Assume you are doing your typescript development in a file named editing.ts

  • In tsconfig.json, add path to editing.ts in files so that it gets transpiled to editing.js by VSCODE.

    "files": [
  • Add jQuery.d.ts, jqueryui.d.ts and pqgrid.d.ts in the typings folder of your project.

  • In jqueryui.d.ts, add reference to jQuery type definition file at the top.

    /// <reference path="jquery.d.ts" /> 
  • In pqgrid.d.ts, add reference to jQuery and jQueryUI type definition files at the top.

    /// <reference path="jquery.d.ts" /> 
    /// <reference path="jqueryui.d.ts" /> 
  • In editing.ts, add reference to pqGrid type definition file at the top.

    /// <reference path="../typings/pqgrid.d.ts" /> 
  • Include the editing.js file in the document ( HTML page ).

  • Inside the typescript file, use pq.grid constructor function to get intellisense support for object properties.

    In this case grid is pqgrid instance and any methods called on grid automatically get intellisense support.

    let grid = pq.grid("#grid_md", {
        width: 800,
        height: 550,

    Alternative way to construct grid.

    let $grid = $("#grid_md").pqGrid( obj );
    //cast jquery object to grid instance.
    let grid:pq.gridT.instance = $grid.pqGrid('instance');

    pq.gridT.options interface can be used to define constructor object separately

    let gridObject:pq.gridT.options = {
        width: 800,
        height: 550,

    Similarly different objects can be defined separately with help of interfaces.


Significance of

The grid data is stored in in the form of an array of rows. When we use local paging, contains all the data of all the pages, while in case of remote paging, contains the data for current page only. In the latter case, is refreshed every time we move from page to page or we hit refresh button in the pager. In case of local filtering, contains only the filtered rows, as unfiltered rows are stored in a different variable dataModel.dataUF.

Special Variable Names

These are some of the variable names used in API and examples which are named so by convention.

$grid is the name of jQuery object that refers to grid container div.

            var $grid = $( ".selector" ); // e.g., $( "#grid_json" );

            //it can also be obtained from inside event callback functions.
            var $grid = $( ).closest( '.pq-grid' );

            //it can also be obtained from grid variable.
            var $grid = grid.widget();
All pqgrid methods can be called with this variable as
            $grid.pqGrid( 'method_name', parameters );

grid is the name of javascript object that refers to a live instance of pqGrid.
            var grid = pq.grid( "#grid_json", options ); //constructor (>= v3.2.0)

            //it can also be obtained from $grid variable as.
            var grid = $grid.pqGrid('instance'); //jQueryUI >= v1.11

            var grid = $grid.pqGrid('getInstance').grid;

            //can also be obtained directly from context of event callback functions.
            var grid = this;
All pqgrid methods can be called with this variable as
            grid.method_name( parameters );

rowIndx is zero based index of a row relative to page 1, row 1. So first row has rowIndx = 0, 2nd row has rowIndx = 1 and so on. It's easy to get reference to a row data if rowIndx is known. For example if we need a reference to 50th row, we can simply get it as var rowData =[49]; where 49 is rowIndx of 50th row. It would work the same whether we use local paging, remote paging or no paging at all.

rowIndxPage is zero based index of a row relative to the current page. There are number of instances when rowIndxPage is easier to use as compared to rowIndx e.g., while inserting a new row on the current page. Also when we use remote paging, rowIndxPage makes better sense as contains data on current page only.

We require records per page and current page number when we wish to calculate rowIndxPage from rowIndx and vice versa. For example if there are 20 rows per page and we are currently on page 3, then rowIndxPage of the row (whose rowIndx is 49) is 9. To save oneself from the trouble of doing the calculations, most of the methods accept rowIndx or rowIndxPage as argument. Similarly most of the events provide rowIndx or rowIndxPage as parameters to be utilized in callback functions.

rowData signifies data for a row, it is extracted from the grid data by[ indx ] where indx is substituted by rowIndx in case of local data, while rowIndxPage in case of remote paging.

dataIndx is the name of field/key in JSON data or numeric index of field in array data. A field or cell value can be obtained from row data by rowData[ dataIndx ].

colIndx is zero based numeric index of column in colModel array. column and hence its properties can be accessed from colModel as colModel[ colIndx ]. It also signifies the physical order of a column, so column with colIndx of 0 is at the leftmost corner of the grid and so on.

vci is zero based visible index of column in grid. It signifies the visible physical order of a column in grid. It's different from colIndx only if there are hidden columns in the grid. This variable is mostly useful for UI testing purpose.

Call pq methods

There are 2 different syntactic ways to call pq methods having same end result:

  1. First one is the use of widget name $( ".selector" ).widgetName( 'method_name', parameters ); e.g., $grid.pqGrid( 'refreshRow', { rowIndx: 2} ) where $grid is the jQuery object wrapped on grid container DOM element. This one is safer ( in the sense it prevents accidental or intentional calling of pqGrid private methods ) but it's verbose, bit slower and garbles up the call stack with intermediate calls to jQueryUI framework.

    This way of method calling is used for jQuery only.

  2. Second one is use of widget instance instance.method_name( parameters ) e.g., grid.refreshRow( { rowIndx: 2 } ) where grid is a live instance of pqGrid. This one is faster and concise.

    This way of method calling is used for Angular, jQuery, React or Vue.

Use pq events

PQ has a powerful event system to inform about interesting points in the lifecycle of widget.

Event listeners are implemented by writing a callback function that is called by the widget when the specified event occurs. Every event listener function has 2 arguments: event and ui where

  • event is an object that provides information about the event in terms of type of event, target, currentTarget, coordinates (pageX, pageY, etc) of the event in case of keyboard or mouse event,
  • ui is an object that provides information about grid specific properties, e.g., rowIndx, rowData, colIndx, dataIndx, etc.

There are 3 ways to bind pq events.

  • 1st and 2nd ways can be used with Angular, jQuery, plain js, React and Vue
  • 3rd one is for use with jQuery only.
  1. Use callback options while initialization i.e.,
                    pq.grid( selector, {                     
                        beforeSort: function( evt, ui ){
                            //code here 
                        //other options.
    or set options after initialization i.e.,
                    grid.option( "beforeSort", function( evt, ui ){
                        //code here 
    This one is fast and easy way to listen to events but has limitation of one callback per event and can't listen to bubbled events.

  2. Use instance listeners that are bound directly to instance of widget. For example to listen to beforeSort event, it's
                grid.on( "beforeSort", function( evt, ui ){
                    //code here.
    Multiple event listeners can be implemented and multiple events can be specified in a single call by specifying space separated list of events. one and off are also supported for instance listeners. This is also easy and quick way of binding event listeners but these can't be used to listen to bubbled events. If more than one listener is implemented for a single event, they are called in the same order as they are added.

  3. Bind event listeners to DOM elements with jQuery API.
                $( ".selector" ).on( "pqGrid:beforeSort", function( evt, ui ){
                    //code here.
    It's disabled by default for performance reasons. It can be turned on by setting trigger option to true.

DOM events and bubbling ( applicable to jQuery/ plain js only ): By default the PQ events are not emitted to DOM elements since v3.2.0 which if required can be turned on by specifying trigger option in the widget to true. The events also don't bubble by default since v3.2.0. Consider case of nested grids where event listener is bound to outer grid for some event; when same event is emitted by inner grid event bubbling leads to invocation of event listener of the outer grid. This can lead to issues unless we are careful to check the currentTarget of event. Again if required, bubbling can be turned on by setting option bubble to true.

Order of events: When more than one event listener for a single event are implemented together, the event listeners are called in this order: instance listeners, DOM event listeners and then callback option. It's possible to call stopImmediatePropagation() on the event object to stop further handling of the event by other pending listeners. It's also possible to stop further propagation to parent handlers or bubbling of event by returning false or calling stopPropagation() on the event object.

Context of events: The context ( i.e., this variable ) is instance of the grid inside callback options ( 1st way ) and instance listeners ( 2nd way ), while it's a reference to DOM element of the widget inside DOM event listeners ( 3rd way ).

Summary of differences between versions:

Feature version < v3.2.0 version >= v3.2.0
Instance listeners Not available. Available
Event type widgetName + "event name" all in lowercase e.g., pqgridbeforesort widgetName+":event name" e.g., pqGrid:beforeSort
Context i.e., this of callback options and instance listeners DOM element of the widget instance of the widget in instance listeners while DOM element of the widget in DOM event listeners
Bubbling and emission of events on DOM nodes true by default false by default

How to refresh the data or view of grid

pqGrid tries to refresh view on its own prior to version 2.0.2 in most cases when dataModel properties are changed. This behaviour is sometimes undesirable e.g. consecutive calls to API changing dataModel properties may lead to undesirable refreshes and reloads of data which is not good for performance. This has changed starting from 2.0.2 whereby the data or view of grid can be refreshed in a more controlled manner. pqGrid can be refreshed in various ways depending upon what or which part of the grid needs to be refreshed. Please see the below comparison table to know which method to use:

refresh refreshView refreshDataAndView
Refresh Column Header Yes Yes Yes
Refresh view for updated rows Yes Yes Yes
Refresh view for added rows No Yes Yes
Refresh view for removed rows No Yes Yes
Reload data from server (location = 'remote') No No Yes
Reload data from (location = 'local') - Yes Yes
Refresh local paging No Yes Yes
Refresh local sorting No No Yes
Refresh local filtering No No Yes
Refresh row grouping No Yes Yes
Refresh cell merging No Yes Yes

Performance tips

If you are updating lot of rows let's say hundreds or thousands of them with API methods such as updateRow, addClass, removeClass, attr, removeAttr, the grid is bound to get slow because the view is refreshed by these methods by default and DOM updates are inherently slow. In order to prevent refresh of view with each method call, refresh parameter to these methods can be passed as false and one final consolidated refresh can be done with a call to refresh method in the end.

Note: addRow, updateRow & deleteRow accept multiple rows in a single method call as of version 3.2.0.

Same logic can be applied to other methods in the API which cause a view refresh e.g., addRow, deleteRow. These methods also accept refresh as parameter which can be passed as false. But instead of refresh, these require refreshView in the end because these methods change the number of rows.

There are few callbacks such as column.render & rowInit in which view refresh is not required and is unnecessary waste of resources. These callbacks are invoked at a time when view of the grid is being prepared and refresh of the view is anyway due after these callbacks. So for performance sake it's prudent to pass refresh: false as parameters if any of these methods addClass, removeClass, attr, removeAttr are called from these callbacks.

List of classes

The grid uses jQueryUI css framework or bootstrap css framework to style its look and feel. Looks can be further customized by the following main classes.

  • pq-grid It is the outermost class of the grid container.
    • pq-grid-topTopmost region of the grid.
      • pq-grid-titleTitle of the grid.
      • pq-toolbarToolbar of the grid.
    • pq-grid-center Center region of the grid containing grid column headers and main table.
      • pq-grid-header-table.Class of the header table.
        • pq-grid-title-row.
          • pq-grid-col, pq-grid-col-leaf.
      • pq-grid-tableClass of the main table.
        • pq-grid-row.
          • pq-grid-number-cell, pq-grid-cell.
    • pq-grid-bottom Bottom region of the grid.
      • pq-grid-footer, pq-pager.

Default options.

The default options of grid are stored in $.paramquery.pqGrid.defaults, of pager in $.paramquery.pqPager.defaults and of scrollbar in $.paramquery.pqScrollBar.defaults. Changing the default options before initialization affects all future instances of the grid, pager and scrollbar.

Any particular grid option ( non objects ) can be set by
$.paramquery.pqGrid.defaults[option] = value;

and a number of default options can be set simultaneously by
$.extend( $.paramquery.pqGrid.defaults, { option1: value1, option2: value2, ... } );

If the options are objects like dataModel, groupModel, sortModel, etc, they can be set as
$.extend( true, $.paramquery.pqGrid.defaults, { dataModel: value1, groupModel: value2, ... } );

Localization Strings

Localization strings for different languages are stored in separate js files e.g., localization file for spanish is pq-localize-es.js The below is a list of some of the localization strings in english.

Please refer to English localization file in SDK for complete reference.

jQuery.paramquery.pqGrid.regional['en'] = {
    strAdd: "Add",
    strDelete: "Delete",        
    strEdit: "Edit",
    //used in row grouping.
    strGroup_header: "Drag a column here to group by that column",
    strGroup_merge: 'Merge cells',
    strGroup_fixCols: 'Fix columns',
    strGroup_grandSummary: 'Grand summary',
    strLoading: "Loading",
    strNextResult: "Next Result",        
    strNoRows: "No rows to display.",        
    strNothingFound: "Nothing found",
    strPrevResult: "Previous Result",
    strSearch: "Search",
    strSelectedmatches: "Selected {0} of {1} match(es)",
    //used in toolPanel
    strTP_aggPane: "Aggregates",
    strTP_colPane: 'Group columns',
    strTP_pivot: "Pivot mode",
    strTP_rowPane: "Group rows",
    strTP_aggPH: "Drop columns for computing aggregate values",
    strTP_colPH: "Drop columns here for grouping along column or x axis",
    strTP_rowPH: "Drop columns here for grouping along row or y axis"
jQuery.paramquery.pqPager.regional['en'] = {
    strDisplay:"Displaying {0} to {1} of {2} items.",		
    strFirstPage:"First Page",
    strLastPage:"Last Page",
    strNextPage:"Next Page",        
    strPage:"Page {0} of {1}",
    strPrevPage:"Previous Page",	
    strRpp:"Records per page: {0}"	

Change Locale

  • Localization strings are similar to default options, hence the procedure to change them is also similar. The following lines of code change the locale of all pqGrid instances in the whole document. These lines should be added after the paramquery grid and localization js files are loaded but before initialization of pqGrid.
    $.extend($.paramquery.pqGrid.defaults, $.paramquery.pqGrid.regional[locale]);
    $.extend($.paramquery.pqPager.defaults, $.paramquery.pqPager.regional[locale]);
    where locale is to be substituted with the locale name.
    For example if it's desired to change the locale to japanese, pq-localize-ja.js file should be included in the page and the below two lines should be added.
    $.extend($.paramquery.pqGrid.defaults, $.paramquery.pqGrid.regional['ja']);
    $.extend($.paramquery.pqPager.defaults, $.paramquery.pqPager.regional['ja']);

  • If it's required to change locale or localization strings for a specific grid, then use the following before initialization, where obj is constructor object for that grid.
    $.extend(obj, $.paramquery.pqGrid.regional['zh']);
    $.extend(obj.pageModel, $.paramquery.pqPager.regional['zh']);

  • Any particular localization string or strings for a particular grid can be set or changed just like normal options e.g.,
    $grid.pqGrid({ strNoRows : 'No Rows found.' });
    $grid.pqGrid( 'option', { strNoRows : 'No Rows found.' });

Angularjs Integration

For Angularjs integration, please check Angularjs grid

Knockoutjs Integration

Knockoutjs is a javascript library that helps you simplify dynamic JavaScript UIs with the Model-View-ViewModel (MVVM) pattern. It is assumed that you are already familiar with and possess working knowledge of Knockoutjs. This section is relevant to implementation of ParamQuery grid in Knockout or migrate your existing jQuery implementation to Knockout. It's important to bear in mind that although existing API of the grid remains the same with only few minor additions, yet you are expected to plan and organize your code in Knockoutjs way i.e., in form of models, views and viewModels rather than writing traditional DOM event handlers.

First of all we include additional dependencies ( in addition to the files mentioned in the include files section):

  1. Knockout.min.js which can be downloaded from
  2. ko.pqgrid.min.js which contains custom bindings of pqgrid for Knockoutjs.

We define the grid options as model properties in the viewModel.

var gridModel = function(){
    var self = this;
    self.items = ko.observableArray(ko.utils.arrayMap(data, function(item){
        return new company(item);

    self.gridOptions = {        
        height: 'flex',
        maxHeight: 400,
        colModel: [
            { title: "Rank", dataIndx: 'rank' },
            { title: "Company", dataType: "string", dataIndx: "company",
                //filter:{ type: 'textbox', condition: 'contain', listeners: ['keyup'] } // for < v5.2.0
                filter:{ crules: [{ condition: 'contain' }] } // for >= v5.2.0
            { title: "Revenues", dataType: "float", dataIndx: "revenues" },
            { title: "Profits", dataType: "float", dataIndx: "profits" }
        title: "Knockoutjs grid",
        filterModel: {on: true, header: true},
        scrollModel: { autoFit: true },
        dataModel: { data: self.items }

We pass on the grid options as custom binding pqGrid to a div placeholder for grid in our HTML view.

<div data-bind="pqGrid: gridOptions"></div>

API extensions:

  1. column.template: It can be used to write Knockoutjs templates in the grid cells. It should be used cautiously as it slows down the grid scrolling a bit. Example:

And if there is need to access grid API, we can get hold of instance of grid in create callback of grid.

create: function(){
    gridApi = this;
and later on use it to call methods of the grid i.e., gridApi.scrollRow({ rowIndx: 0 });

Further Reading

How to use jQuery UI widgets