Welcome to the ParamQuery Grid tutorial! This guide will help you get started with the advanced features of the ParamQuery Grid, a powerful jQuery plugin for creating data-rich grid interfaces. In this tutorial, we will cover the topics mentioned in the left side menu:
ParamQuery Pro is a highly versatile library that is mainly developed using plain JavaScript, which allows it to be integrated seamlessly with a wide range of frameworks such as Angular, React, Vue, or even used as a standalone library with plain JavaScript or jQuery. The library leverages some parts of jQueryUI components like the datepicker, autocomplete, drag and drop, and position API, to avoid reinventing the wheel. However, if you are using ParamQuery Pro with modern frameworks, you don't need to learn jQuery or jQueryUI as ParamQuery abstracts the jQueryUI API, making it easier for developers to work with the library.
ParamQuery Pro contains 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:
Grid refreshes its view ( and refresh event is fired ) whenever the following takes place:
ParamQuery Grid stores data for local, lazy as well as remote requests in dataModel.data 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:
dataModel.data 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
If you use ParamQuery with npm then you may skip to next section.
To use ParamQuery without npm first of all include these js and css files in the header section of the web page.
Recommended to use jQuery >= v2.2.x and jQueryUI >= v1.12.x
<!--jQuery dependency, any stable version of jQuery--> <script src="https://unpkg.com/[email protected]/dist/jquery.js"></script> <!--jQueryUI version 1.11.4 --> <link rel="stylesheet" href="https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" /> <script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></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" /> <!--Include jsZip file (v2.5.0) before pqgrid js file to support xlsx and zip export (optional)--> <script type="text/javascript" src="path to jsZip.js" ></script> <!--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 jquery.resize to support auto height of detail views in hierarchy (optional)--> <script type="text/javascript" src="path to jquery.resize.js" ></script>
Sample jsfiddle
<!--jQuery dependency, any stable version of jQuery--> <script src="https://unpkg.com/[email protected]/dist/jquery.js"></script> <!--jQueryUI version 1.12, 1.13 --> <link href="https://unpkg.com/[email protected]/jquery-ui.css" rel="stylesheet" /> <link href="https://unpkg.com/[email protected]/jquery-ui.structure.css" rel="stylesheet" /> <link href="https://unpkg.com/[email protected]/jquery-ui.theme.css" rel="stylesheet" /> <script src="https://unpkg.com/[email protected]/jquery-ui.js"></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" /> <!--Bootstrap icons support (optional)--> <link rel="stylesheet" href="path to pq-icons/pq.css" /> <!--Include jsZip file (v2.5.0) before pqgrid js file to support xlsx and zip export (optional)--> <script type="text/javascript" src="path to jsZip.js" ></script> <!--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>
Sample stackblitz
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.
Compatibility chart between jQuery and jQueryUI
jQuery | jQueryUI |
---|---|
v2.x.x | v1.11.4, v1.12.x, v1.13.x |
v3.x.x | v1.12.x, v1.13.x |
Evaluation version of pqgrid can be installed though a nodejs package manager e.g, npm or yarn.
npm i pqgrid
Commercial or OEM version of pqgrid can be installed as a local npm package by pointing "pqgrid" to local file system path in the package.json file -> dependencies section in the project manually.
"dependencies": { ... "pqgrid": "file:local path to paramquery folder", ... }
pqgrid has following peer dependencies which can also be installed through a package manager.
jquery jquery-ui-pack @types/jquery @types/jqueryui jszip
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 commonly in styles.css 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'; @import '~pqgrid/pq-icons/pq.css'; /* optional; since version 9.0.0 */
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.
$(function(){ //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 ); //or pq.grid("#grid_json", obj ); });
In the body tag define the div tag/tags which act as placeholders for the grid.
<div id="grid_json"></div>Sample jsfiddle
Note: Angular, React and Vue users may skip this topic.
Within the DOMContentLoaded event callback function, initialize the grid as pq.grid( ".selector", 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.
document.addEventListener("DOMContentLoaded", function(event) { //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} }; pq.grid("#grid_json", obj ); });
In the body tag define the div tag/tags which act as placeholders for the grid.
<div id="grid_json"></div>Sample jsfiddle
ParamQuery adds so much functionality to Angular applications which is not possible otherwise.
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.
npm install
or yarn
ng serve
or npm run ng serve
localhost:4200
(as mentioned in message of your command window) in your browser.ParamQuery adds so much functionality to React applications which is not possible otherwise.
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.
npm install
or yarn
in the command promptnpm start
in command promptlocalhost:4200
(as mentioned in message of your command window) in your browser.ParamQuery adds so much functionality to Vue applications which is not possible otherwise.
ParamQuery is written mostly in pure javascript and has no internal dependency on Vue API; it's compatible with all Vue versions and is immune to any breaking changes w.r.t different Vue versions.
pqgrid can be added in any Vue project using either of the following ways:
First of all include pqgrid and its dependencies using script/link html tags as mentioned above in Include Files section
Include vue.js file with script tag e.g.,
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
Then define a pqGrid component as follows:
Vue.component("pq-grid", { props: ["options"], mounted: function () { pq.grid(this.$el, this.options); }, template: '<div :options="options"></<div>' });Sample stackblitz
First create a new vue-cli project or use an existing vue-cli project
npm i -g @vue/cli
vue create hello-world
Pick any preset:
cd hello-world
npm run serve
Browse http://localhost:8080/ in your browser to verify the project
Terminate the running Vue.js project by pressing Ctrl-C twice in command prompt.
Open hello-world folder in vs code. Edit package.json file, add pqgrid and its peer dependencies in "dependencies" section:
"pqgrid": "^9.1.1", "@types/jquery": ">=2.2.1", "@types/jqueryui": ">=1.12.21", "jquery": ">=2.2.1", "jquery-ui-pack": ">=1.12.3", "jszip": "2.5.0"
Use yarn or npm on command prompt to install the newly added dependencies in package.json
Add a PqGrid.vue file in the src/components folder with following content.
<template> <div :options="options"> </div> </template> <script> import pq from 'pqgrid' //import a localization file import 'pqgrid/localize/pq-localize-en.js'; require('jquery-ui-pack/jquery-ui.css'); require('jquery-ui-pack/jquery-ui.structure.css'); require('jquery-ui-pack/jquery-ui.theme.css'); require('pqgrid/pqgrid.min.css') require('pqgrid/pqgrid.ui.min.css') require('pqgrid/themes/bootstrap/pqgrid.css') export default { name: 'PqGrid', props: ["options"], mounted: function () { console.log(this.options); pq.grid(this.$el, this.options); } } </script>
Add following in template section of App.vue
<PqGrid :options="options"></PqGrid>
Add import of PqGrid in App.vue
import PqGrid from './components/PqGrid.vue'
Add PqGrid in components and add pqgrid options inside data()
export default { name: 'App', components: { PqGrid, ... }, data() { return { options: { showTop: false, reactive: true, locale: 'en', height: "flex", ... } } } }
Any eslint rules can be updated or added in package.json -> eslintConfig section
Run the project again with npm serve or yarn serve
Download sample project, build and run it using npm or yarn. $grid.pqGrid( 'option', 'dataModel.data', 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.
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.
For lazy / 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.
Type | Request 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.
Either Paramquery or jQueryUI themes can be used
ParamQuery themes | jQueryUI themes | |
---|---|---|
Name |
|
|
Usage |
Include corresponding theme file from ParamQuery SDK e.g., to use green theme, include "..themes/green/pqgrid.css" file
Use corresponding pqgrid.rtl.css for RTL languages.
|
Include theme file from jQueryUI SDK. |
Icons are used at many places in the grid e.g. in toolbar, pager, grouping icons, etc. You have a choice to use any of the following icons.
jQueryUI icons | ParamQuery icons | Bootstrap icons | |
---|---|---|---|
Background image based icons, bundled with jQueryUI | Font based most commonly used icons derived from Bootstrap icons. Included in ParamQuery SDK. | Font based large collection of icons, can be used independently of Bootstrap. Download it from https://icons.getbootstrap.com/ | |
Include | Included by default |
Include pq-icons/pq.css file from PQ SDK in the document
or Add@import '~pqgrid/pq-icons/pq.css'; in styles.css
|
Include in following order:
|
Usage | Assign ui-icon-* classes | Assign either ui-icon-* or bi-* classes | Assign bi-* classes mostly. ui-icon-* classes may also be used |
Pros | Easy to use, can be complemented with custom 16x16px image in absence of appropriate icon |
|
|
Cons |
|
|
Size of files:
|
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();
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": [ "js/editing.ts" ]
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.
pq.gridT.column
pq.gridT.dataModel
pq.gridT.colModel
pq.gridT.groupModel
Significance of dataModel.data
The grid data is stored in dataModel.data
in the form of an array of rows. When
we use local paging, dataModel.data contains all the data of all the pages, while
in case of remote paging, dataModel.data contains the data for current page only.
In the latter case, dataModel.data is refreshed every time we move from page to
page or we hit refresh button in the pager. In case of local filtering, dataModel.data contains only the filtered rows,
as unfiltered rows are stored in a different variable dataModel.dataUF
.
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 evt.target inside event callback functions. var $grid = $( event.target ).closest( '.pq-grid' ); //it can also be obtained from grid variable. var $grid = grid.widget();All pqgrid methods can be called with
$grid
variable as
$grid.pqGrid( 'method_name', parameters );
grid
is the name of javascript object that points to a live instance of pqGrid.
//it's returned by pq.grid constructor. var grid = pq.grid( "#grid_json", options ); //it can also be obtained from $grid variable as. var grid = $grid.pqGrid('instance'); //it can also be obtained directly from this context within event callback functions. var grid = this;All pqgrid methods can be called with
grid
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 = dataModel.data[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 dataModel.data
contains data on current page only.
rowData
signifies data for a row, it is extracted from the grid data by dataModel.data[ 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.
Any row may have following meta data associated with it which help define styles, format, properties, etc of individual cells and rows
Name | Data Type | Read / write | Purpose |
---|---|---|---|
pq_ht | Number | both | Determines height of row |
pq_htfix | Boolean | both | When true, height of row is fixed even if autoRow height option is on. |
pq_hidden | Boolean | both | pq_hidden: true is added to hidden rows. |
pq_level | Integer | Read only | Determines level ( beginning from 0 ) of the title row in row grouping, treegrid, pivot. |
pq_gtitle | Boolean | Read only | true when the row is a title row in row grouping or pivot. |
pq_gsummary | Boolean | Read only | true when the row is a summary row in row grouping, treegrid, pivot. |
pq_grandsummary | Boolean | Read only | true when the row is a grand summary row in grid, row grouping, treegrid, pivot. |
pq_rowattr | Object | both | html attributes of a row e.g., pq_rowattr: { "title": "comments of row"} |
pq_cellattr | Object | both | html attributes of a cell e.g., pq_cellattr: { country: { "title": "comments of cell" }, .. } |
pq_rowstyle | Object | both | css style of a row e.g., pq_rowstyle: { "background-color": "#ffff00", color: "#0000ff", .. } |
pq_cellstyle | Object | both | css style of a cell e.g., pq_cellstyle: {shipName: { "background-color": "#ffff00", color: "#0000ff", .. }, .. } |
pq_rowprop | Object | both | editability, format, align, valign properties of a row e.g., pq_rowprop: { edit: false, align: "center", valign: "top", .. } |
pq_cellprop | Object | both | editability, format, align, valign properties of a cell e.g., pq_cellprop: {shipName: { edit: false, format: 'xxx' .. }, .. } |
pq_rowselect | Boolean | both | selection state of a row when selectionModel.type = 'row' |
pq_rowcls | string | both | space separated list of css classes assigned to a row |
pq_cellcls | string | both | space separated list of css classes assigned to a cell |
pq_filter | Boolean | Read only | When filterModel.hideRows is true, pq_filter is added to filtered out or hidden rows. |
pq_copy | Boolean | both | When set to false, prevents copy of data from that row. |
pq_paste | Boolean | both | When set to false, skips paste of data to that row. |
There are 2 different syntactic ways to call pq methods having same end result:
$( ".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.
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.
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.
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.
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.
$( ".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.
instance listeners > DOM event listeners > callback option.
It's possible to callstopImmediatePropagation()
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 dataModel.data (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 |
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.
Following is the hierarchial structure of pqgrid, different sections in the hierarchy are assigned with different classes:
pq-grid
It is the outermost class of the grid container.
pq-grid-top
Topmost region of the grid.
pq-grid-title
Title of the grid.pq-toolbar
Toolbar 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-table
Class 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
.
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 for different languages are stored in separate js files with their names ending in localization code e.g.,
localization file for spanish is pq-localize-es.js,
for german it's pq-localize-de.js,
for japanese it's pq-localize-ja.js
and so on.
Below are the contents of the localization file pq-localize-en.js
Setting localization of grid during initialization is done by simply including locale js file in the document before initialization of the grid. If multiple localization files are loaded then the last localization file is used.
Localization strings for controls like Bootstrap / jQueryUI dialog, button, colorPicker etc can be obtained from
jQuery.paramquery.strings
which provides the localization strings from the last loaded locale js file.
//change locale to korean. grid.option('locale', 'kr');
$grid.pqGrid({ strNoRows : 'No Rows found.' });or
$grid.pqGrid( 'option', { strNoRows : 'No Rows found.' });
For Angularjs integration, please check Angularjs grid
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):
Knockout.min.js
which can be downloaded from http://knockoutjs.com/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:
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