jqgrid custom sort on local data on different column - sorting

I have a jqgrid where dataytype is local. The automatic sort is working fine for each column. I want to know if it's possible to sort a different column based on another column.
To explain this better Lets assume I have three columns OrderNumber, Address, Phone, and a hidden column named State. When the Address column is clicked I actually want to sort like if the State column would have been the one clicked.
I'm trying to do this on the onSortCol event, I want something like:
onSortCol: function (index, iCol, sortorder) {
if(index === "Address"){
//CHANGE SORTED COLUMN TO STATE AND MAKE THE SORT
}
},

If you work with remote data (datatype:'json' or datatype:'xml') you can implement any kind of sorting very easy. So I suppose that you mean jqGrid with local data in your question. In the case I would recommend you to use sorttype parameter inside of colModel defined as function.
You can define for the Address column the sorttype property which looks like the following:
sorttype: function(cellValue, rowObject) {
return rowObject.State;
}
or like this one:
sorttype: function(cellValue, rowObject) {
return rowObject.State + "_" + cellValue;
}
The parameter cellValue is the contain of the cell which will be used in compare operation to sort the grid. The rowObject is the opject which reprecent the full row having cellValue. Returnung another value as cellValue from the function sorttype will follow that the returened value will be used in the compare operations instead of the cellValue.
In the first example of sorttype implementation (see above) the sorting by Address column will be done based on the contain of the column with the name State. In the second example, the rows having the same state will be additionaly sorted by address.
You can look on the small demo here. If you click on the "Tax" column the grid will be sorted by "id" column where the id values will be interpret as integer.

If you were doing server side sorting you would just do this:
if(sord == "Address"){
sord = "State";
}
Have you tried doing the same for your client side sorting:
onSortCol: function (index, iCol, sortorder) {
if(index === "Address"){
index = "State";
}
},

Related

Free jqGrid. Getting column names in conjunction with a cell

I'm trying to implement a data fullness check with an error output that describes which cells were not filled in the line.
//get row id
var gr = $("#" + subgrid_table_id).jqGrid('getGridParam', 'selrow');
// check row select
if (gr != null) {
/*
var myGrid = $("#" + subgrid_table_id),
selRowId = myGrid.jqGrid('getGridParam', 'selrow'),
//get cell value:
col1Value = myGrid.jqGrid('getCell', selRowId, 'stage');
//get all colnames
var columnNames = myGrid.jqGrid('getGridParam','colNames');
//get column name by index:
var col1Name = columnNames[4];
if (col1Value == "") {
alert("This data is empty: "+col1Name);
}
else {
That is, everything seems to work, but when you change the number of columns, everything can go to waste. How can I link the column name to ColNames with its name in ColModel to get a dynamic solution?
First of all all parameters of jqGrid are saved in one object available by myGrid.jqGrid('getGridParam'). Thus var selRowId = myGrid.jqGrid('getGridParam', 'selrow'); is the same as p.selrow, where var p = myGrid.jqGrid('getGridParam');.
The columns will be identified by the index in the colModel: p.colModel[iCol]. On the other side the name property of the column will be known more frequently as the index of the column iCol. Moreover, there are exist the possibility to reorder the columns by drag and drop of the column headers. One need include sortable: true option of the grid to enable the possibility. The column order can be changed by columnChooser or by direct calls of the methods remapColumns or remapColumnsByName. Because of all the reasons it's recommend to save the name of columns (which will be never changed) instead of the column index.
To get the column index by the column name one can loop over colModel array and test the value of the name property. To speed-up such operation free jqGrid provided the map object iColByName as the option of jqGrid. Thus, if you know the column name cmName then you can use var iCol = p.iColByName[cmName]; to get the column index. The column in colModel will be p.colModel[iCol] and the text of the column header will be p.colNames[iCol].
By the way, I'm not sure that you correctly understand the value of colNames. The name of the parameter is not good, but it will be used because of the compatibility with the old version. The elements of the array colNames are HTML fragments, which will be placed in the column headers. One can have empty strings inside of colNames or to have the same headers for different columns. On the other side the name property of the colModel is the real name of the column. It can't be empty. One can't use duplicate names in different columns and the names can't contains spaces.
I hope that having the above information you will easy able to find full information about every column.
The final remark. There are three main methods, which can be used to get data of the grid: getCell, getRowData and getLocalRow. jqGrid get input data, formats the data and places the formatted HTML fragments in the cells (in <td>). Additionally jqGrid saves the original raw data in internal data parameter (which is array of items, represented the rows). The data parameter exists only in case of using local data (datatype: "local") or in case of loading the data from remote set (datatype: "json" or datatype: "xml"), but with loadonce: true option additionally. The methods getCell and getRowData unformats the data from the cell(s) (from <td>) and the method getLocalRow get you direct reference to internal JavaScript object from internal data, where the data of the row are already set. Thus, it's recommended to prefer to use getLocalRow instead of getCell or getRowData whenever the grid has local data.

yii2 sort gridview on function column

I have a grid view i am populating with a data provider that gets its data from an active query. One of my columns is displayed via a function in the view that evaluates data from 2 different tables and displays one or the other value (based on date) i would like to be able to sort this column, but because its not part of the original SQL statement the ORDER BY clause created by the sort widget is not aware of the column to sort on. My question is, is there a way to sort the data after it has been passed and loaded into the grid view, or is there a better way to gather the data retrieved from the function so that it can be sorted.
[
'label'=>'Last Backup Date',
'value'=>function($data)
{
if(!is_null($data->backupEvent) && !is_null($data->backups))
{
return MAX($data->backupEvent->eventTime,$data->backups->fieldValue);
}elseif(!is_null($data->backupEvent))
{
return $data->backupEvent->eventTime;
}elseif(!is_null($data->backups)) {
return $data->backups->fieldValue;
}
}
],

Remove blank column in jqGrid - Pivot

I have created a jqGrid - Pivot table JSFiddle example: here.
In this It should not print the line if Component Type value is blank, I Used this empty column, to show all periods(months) in the year, which is mandatory.
Need help in removing that blank line. and also is it possible to remove the last sum column 2015 from grid, if so how?
You includes dummy data with ComponentType:"" group which you don't want to display. So the best solution which I see would be to include the data in the input pivot data only, but don't use the dummy data in the grid data. jqPivot uses datatype: "jsonstring" to prevent additional sorting of previously sorted data. The input data will be placed as the value of datastr option. So one can use the following onInitGrid to remove the dummy data before the data will be processed by jqGrid:
onInitGrid: function () {
var p = $(this).jqGrid("getGridParam"),
userdata = p.datastr.userdata;
p.datastr = $.grep(p.datastr, function (item) {
return item.ComponentType !== "";
});
p.datastr.userdata = userdata;
}
see the modified demo http://jsfiddle.net/OlegKi/b47ocLd7/11/.

Ignore case while grouping

Is there a way to tell the jqGrid to ignore the case while grouping? I don't want to change the data as some will be upper case, some lower case and others mixed case.
I'm using jqGrid 4.4.4
The question is good, but ... the current implementation of grouping in jqGrid allow grouping only exact values. I remember close requirements when one wanted to group by month instead by exact date.
After some analyse of the source code of jqGrid I hope that I found very simple and very flexible way to do more flexible grouping. I suggest to modify the line
if( typeof v !== "object" && grp.lastvalues[i] !== v ) {
to
if (typeof v !== "object" &&
($.isFunction(grp.isInTheSameGroup) ?
!grp.isInTheSameGroup(grp.lastvalues[i], v) :
grp.lastvalues[i] !== v)) {
After this one can define isInTheSameGroup function inside of groupingView:
grouping: true,
groupingView: {
...
groupField: ["name"], // the column by which we group
isInTheSameGroup: function (x, y) {
return String(x).toLowerCase() === String(y).toLowerCase();
}
}
The demo display the following results:
I used in the demo modified version of jquery.jqGrid.src.js of jqGrid 4.4.5. The version of jquery.jqGrid.src.js of jqGrid 4.4.4 modified in the same way you can find here.
I will post later my suggestion to trirand. I hope that the next version of jqGrid will contain the feature.
UPDATED: As promised, I posted the corresponding feature request to trirand.
UPDATED 2: I posted the pull request with a little more changes of grouping module of jqGrid. The demo demonstrates how new features can be used. It uses 2-level grouping and displays the following results:
UPDATED 3: The pull request which I sent to trirand is merged now to the main code of jqGrid. So the next version of jqGrid (after 4.4.5) will supports isInTheSameGroup and formatDisplayField arrays of callbacks inside of groupingView. If your case it would look like
groupingView: {
groupField: ['name'],
formatDisplayField: [
function (displayValue) { //, value, cm, index, grp) {
return String(displayValue).toLowerCase();
}
],
groupColumnShow: [true],
groupDataSorted: true,
isInTheSameGroup: [
function (x, y) {
return String(x).toLowerCase() === String(y).toLowerCase();
}
]
}
The callbacks isInTheSameGroup[0] and formatDisplayField[0] will be used by grouping by groupField[0]. Because jqGrid support multilevel grouping the isInTheSameGrou and formatDisplayField properties are arrays of callback functions instead of just callback function.
At the beginning of grouping jqGrid sort data by grouping column. One can use sorttype defined as function to customize the first step (see the answer). I don't though about the step during writing of your answer. Probably usage of sorttype: function (cellvalue) {return String(cellvalue).toLowerCase();} could already solve your problem.
Then the function isInTheSameGroup[level] will be used consequently to compare the value of grouping column from of previous row with the corresponding value of the current row. The function isInTheSameGroup[level] will be called with the values. If your callback returns true then the row will be grouped with the previous one.
The callback formatDisplayField[level] allows to customize the information displayed in the grouping header. In the example above I convert the data to low case.

idPrefix usage in jqGrid

Given a jqGrid populated with local data and created with the option of idPrefix:"custTable" , all the generated rows get the prefix in the html id i.e. custTableRow_1 custTableRow_2 etc. Does this idPrefix'ed version of the id need to be passed in to the jqGrid methods, if so which ones?
for example to delete a row with deleteRowData does it need the prefixed id? how about setRowData or addRowData? when adding after row x it seems to need the prefixed for the srcrowid parameter. How about multiselect rows?
If I delete a row using the prefixed id of the row it disappears from the display but when I reload the grid the delete item shows up again in the grid, like it wasn't removed. This doesn't happen when idPrefix is not used.
thanks for any help.
The option idPrefix was introduced to hold ids on the HTML page unique even you have on the page the ids like the rowids loaded from the server. Typical example is two grids with the data loaded from the server. Let us you have two tables in the database where you use IDENTITY or AUTOINCREMENT in the definition of the PRIMARY KEY. In the case the primary key will be generated automatically in the table and will be unique inside the table, but there are not unique over the tables. So if you would use the primary keys as ids of the grids and place on one page two grids you can have id duplicates.
To solve the problem you can use idPrefix: "a" as additional option in the first grid and use idPrefix: "b" in the second grid. In the case locally jqGrid will uses everywhere ids with the prefix, but the prefix will be cut if the ids will be sent to the server.
So you will see locally in all callbacks (events) and in all methods (like setRowData, addRowData etc) the ids with the prefix, but on the server side the ids the prefixes will be removed immediately before sending to the server.
I recommend you additionally to read another answer about the restrictions in the ids which I posted today.
UPDATED: I looked through the code which you posed on jsfiddle and found some clear bugs in your code. You current code
1) use wrong algorithm to generate id of the new row. For example the following code
// generic way to create an animal
function newAnimal(collection, defaults) {
var next = collection.length + 1;
var newpet = {
id : next,
name: defaults.name + next,
breed: defaults.breed
};
return newpet;
}
use collection.length + 1 for the new id. It's wrong if you allows to delete the items. By adding of two items, deleting one from there and adding new item one more time follows to id duplicates. Instead of that it's more safe to use some variable which will be only incremented. You can use $.jgrid.randId() for example which code is very simple.
2) you call addRowData with adding a prefix manually (see dogsPrefix+newdog.id below). It's wrong because jqGrid adds the prefix one more time to the rows.
// add dog button actions
$('#dogAddAtEnd').click(function() {
var newdog = newAnimal(dogs, dogDefaults);
dogs.push(newdog);
dogAdded();
dogsTable.jqGrid('addRowData', dogsPrefix+newdog.id, newdog);
});
Probably there are more problems, but at least these problems can explain the problems which you described.
UPDATED 2: I examined new demo which you posted. It has still the lines
grid.jqGrid('addRowData', newanimal.id, newanimal,
"after", prefix+ followingId);
and
dogsTable.jqGrid('addRowData', dogsPrefix+newdog.id, newdog);
which must be fixed to
grid.jqGrid('addRowData', newanimal.id, newanimal,
"after", followingId);
and
dogsTable.jqGrid('addRowData', newdog.id, newdog);
Nevertheless I tested the demo after the changes and found bugs in code of addRowData, delRowData and setRowData. The problem are in the line of the delRowData and the same line of setRowData
var pos = $t.p._index[rowid];
can be fixed to the following
var id = $.jgrid.stripPref($t.p.idPrefix, rowid), pos = $t.p._index[id];
Inside of addRowData I suggest to include the line
var id = rowid; // pure id without prefix
before the line
rowid = t.p.idPrefix + rowid;
of addRowData. Another tow lines of addRowData
lcdata[t.p.localReader.id] = rowid;
t.p._index[rowid] = t.p.data.length;
should be changed to
lcdata[t.p.localReader.id] = id;
t.p._index[id] = t.p.data.length;
where unprefixed id will be used.
The modified code of you demo which uses the fixed version of jquery.jqGrid.src.js you can test here.
I will post my bug report to trirand later to inform the developer of the jqGrid. I hope that soon the bug fix will be included in the main code of jqGrid.
Additionally I recommend you to use $.jgrid.stripPref method to strip prefixes from the rowids. For example the function
//general delete selected
function deleteSelectedAnimal(list, grid, prefix)
{
var sel = grid.jqGrid('getGridParam', 'selrow');
if (sel.length)
{
var gridrow = sel;
//get the unprefixed model id
var modelid = gridrow;
if (prefix.length !== 0)
{
modelid = modelid.split(prefix)[1];
}
// make it a numeric
modelid = Number(modelid);
//delete the row in the collection
list = RemoveAnimal(list, modelid);
//delete the row in the grid
grid.jqGrid('delRowData', gridrow);
}
}
from your demo can be rewritten to the following
//general delete selected
function deleteSelectedAnimal(list, grid)
{
var sel = grid.jqGrid('getGridParam', 'selrow'),
gridPrefix = grid.jqGrid('getGridParam', 'idPrefix');
if (sel !== null)
{
//delete the row in the collection
// ??? the gogs list will be not modified in the way !!!
list = RemoveAnimal(list, $.jgrid.stripPref(gridPrefix, sel));
//delete the row in the grid
grid.jqGrid('delRowData', sel);
}
}
I am not sure that the line list = RemoveAnimal(list, $.jgrid.stripPref(gridPrefix, sel)); or the function RemoveAnimal do what you want, but it's not a problem which connected with jqGrid.
One more small remark about your code. You use already in the objects which you add to the grid the id property. It's the same name as defined in the localReader.id. In the case the data from the id property will be used as id attribute of the grid rows (<tr>). The local data parameter will save the id additionally to other properties which are build from the name property of the items of colModel. So I see no sense to define hidden column
{ key: true, name: 'id', align: 'left', hidden: true }
How you can see on the demo all stay works exactly as before if you remove id column from the grids which you use.
UPDATED 3: As promised before I posted the corresponding bug report here.

Resources