I have a jqGrid that I set up like this
gridAltMpn.jqGrid({
autowidth: true,
shrinkToFit: true,
datatype : 'local',
data : input,
height : '100',
scrollrows: true,
scrollOffset : '0',
hidegrid : false,
colNames : [ 'P', 'MPN' ],
colModel : [
{ name : 'Col1', width : 30, align:'center' },
{ name : 'Col2', width : 250, sorttype: 'integer'}
],
pager : '#altmpn_pager',
pagerpos : 'left',
scroll: 50,
gridview : true,
caption : 'A useful table title',
emptyRecordText : '<div id="no_data_msg" style="text-align:center"> No Results Found</div>',
hoverrows : true,
onSelectRow: function(id) {
var gsr = gridAltMpn.jqGrid('getGridParam', 'selrow');
if (gsr) {
var rowData = gridAltMpn.jqGrid('getRowData', gsr);
if ($("input[name='optInvInqType']:checked").val() == 'MPN') {
getInvInq("MPN", rowData.MPN);
}
}
},
loadComplete: function() {
gridAltMpn.setSelection(gridAltMpn.getDataIDs()[0], true);
}
});
The data in this grid looks like this
XX 774860A6
774860A8
774860A4
774860A3
774860A10
STARTER, PNEUM,PW4000
When the grid is first loaded that it fine but if the user wants to sort by the second column it ends up like this
774860A10
774860A3
774860A4
XX 774860A6
774860A8
STARTER, PNEUM,PW4000
The 774860A10 should go after the 774860A8 just like in an integer sort. I cannot use an integer sort because these are not integers as there is some alpha characters in there. In other words I want a text entry to sort like an integer. Do I need to use a custom sort routine and then have my Javascript to do a integer like sort? I also don't need this sorted on the first time because my server sorts it by the first column. The user might want it sorted by the second column
You should use a custom function for this type of sorting.
For this, set sort type property of jqgrid as your custom function. As stated in this link, sort type can have the following values.
sorttype:
int/integer - for sorting integer
float/number/currency - for sorting decimal numbers
date - for sorting date
text - for text sorting
function - defines a custom function for sorting. To this function we pass the value to be sorted and it should return a value too.
And the custom function can be something like this: (From this link found in the answer by Oleg for this question.)
colModel: [
{name:'Posn', index:'Posn', width:100, sorttype:
function(cell)
{
//Here you have to apply your own logic
if (cell=='GK') return '0';//returns the sort order
if (cell=='DEF') return '1';
if (cell=='MID') return '2';
if (cell=='STR') return '3';
}
},
By the way, you can set the sortname property of jqgrid to set a column for initial loadtime sorting.
Related
I like to change the Type field drop down option depending on the inputs of Year and Level fields.
I am able to trigger an event when Level is change.
But how do I get the value of the Year field?
Portion of the code are as follows
colModel:[
{name:'Year',index:'Year', width:70,sortable:false,editable:true,align:'center',editoptions:{size:15, maxlength:4}, formoptions:{ rowpos:1, label: "Year (*)"},editrules:{required:true}},
{name:'Level',index:'Level', width:70,sortable:false,editable:true,align:'center',edittype: "select", editoptions: { value: '1:1;2:2;3:3;4:4;5:5;6:6', defaultValue:'1', dataEvents : [
{
'type' : 'change',
'fn' : function ( el ) {
// get the newly selected value from the user
var levelz = $(el.target).val(), yearz ;
var row = $(el.target).closest('tr.jqgrow');
var rowid = row.attr('id');
//yearz = ??
if (parseInt(levelz)==5 || parseInt(levelz)==6)
{
if (parseInt(yearz)>2017)
{
$("#gridmain").jqGrid('setColProp','Term', {editoptions: { value: '1:Sem 1;4:Sem 2;6:EY;9:OVR', defaultValue:'Sem 1'}} );
}else{
$("#gridmain").jqGrid('setColProp','Term', {editoptions: { value: '', defaultValue:''}} );
}
}else{
$("#gridmain").jqGrid('setColProp','Term', {editoptions: { value: '1:TA1/CT1;2:TA2-before 2013;3:MY/TA2/CT2;4:TA3/CT3;5:TA4-before 2013;6:EY/TA4/CT4;9:OVR;D:CW1;E:CW2;F:CW3;G:CW4', defaultValue:'TA1'}} );
}
}
}]}, formoptions:{ rowpos:2, label: "Level (*)"},editrules:{required:true}},
{name:'Term',index:'Term', width:70, sortable:false,editable: true,align:'center',edittype: "select", editoptions: { value: '1:TA1/CT1;2:TA2-before 2013;3:MY/TA2/CT2;4:TA3/CT3;5:TA4-before 2013;6:EY/TA4/CT4;9:OVR;D:CW1;E:CW2;F:CW3;G:CW4', defaultValue:'TA1'}, editrules: { required: true }, formoptions:{ rowpos:3, label: "Type"}},
The codes are from piecing together what I read from google search...
I face 2 issues:
1) I don't know how to get the Year value
2) The drop down option list doesn't seems to change. - hmm it seems that if I close the edit form and open again, the Type field drop down option changes. What I need is to change the option on the fly - wonder how this can be done...
After much googling, managed to get the ans from Oleg's post as shown here
Also from his example, I derive the year value:
var yearz = $("#Year.FormElement", form[0]).val();
I am trying to make a grid groupable on columns field but the columns are object.
{
Gestionnaire :
{ id: 4, nom:'nomgestionnaire'},
{..},
..
}
I have success for sortable:
columns: [
field: "Gestionnaire"
title: "Gestionnaire"
sortable:
compare: (a,b) =>
#compareColumnFields(a.Gestionnaire.Nom, b.Gestionnaire.Nom)
]
with #compareColumnFields function is :
if a is b
return 0
else if a > b
return 1
else
return -1
and for groupable?
groupable : ...
I think you're wanting to allow the user to actively group columns.
In that case, all you need is:
groupable: true
in the main structure of the grid.
For example:
$('#grid').kendoGrid({
columns: [
{
fields: "Guestionaire",
title: "Guestionaire",
sortable:
compare: (a,b) =>
#compareColumnFields(a.Guestionaire.Nom, b.Guestionaire.Nom)
},
{...placeholder for other columns...}
],
groupable: true
});
Kendo has a sample of this at http://dojo.telerik.com/ejehe
Ignore the SelectRow and Expand/Collapse stuff and that ought to be the same as what you're trying to accomplish.
For those in the same situation as me , I completely change solution. Instead of making me a function that returns true and false , it giving it the object in full, I just give the string .
For my example I give directly a.Gestionnaire.Nom and b.Gestionnaire.Nom, and THEN you can call :
groupable: true
In fact it was obvious.
I am using jQrid version 3.8.1 and I have a grid that displays information about cars. The jQgrid should is set up to display one car per row and one of the columns is a multi-select list that displays which types of seats the car is configured with. A car can have multiple seat types.
When the user edits a car row, it makes an ajax query to get all of the seats types available in the system and sticks them in the multi-select list. In addition to populating the list, it needs to also select the options already chosen for that car.
The values inside the Installed Seats column are not simple strings. They have both an ID and a string value. So the ID for "Wire mesh" might be 2883 and the value for "Composite" might be 29991. They are just unique numeric values (basically the primary key from the table they are stored in).
After the multi-select list is populated with all the appropriate Seat values, I need to select the ones that the car currently has installed (in the picture above it's "Steel" and "Wire frame"). I need to do this based on the seat IDs stored for that car. However, I don't know where these value are going to come from. The grid only stores the names for the seats, not the IDs. Hopefully there is a way to make it store both.
The column model looks like this:
colModel: [
{ name: 'Year', index: 'Year', editable: true, edittype: "select", editoptions: { multiple: true } },
{ name: 'Make', index: 'Make', editable: true, edittype: "select", editoptions: { multiple: true } },
{ name: 'Body', index: 'Body', editable: true, edittype: "select", editoptions: { multiple: true } },
{ name: 'Seats', index: 'Seats', editable: true, edittype: "select", editoptions: { multiple: true }, cellattr='is-seat-list="1"' }
]
Notice that the 'Seats' model has a cell attribute called is-seat-list. I'm using this to find the select box in the row inside the 'editRow' function.
The onSelectRow handler looks like this:
onSelectRow: function (index) {
var curValues = $('#cargrid').getRowData(index);
jQuery('#cargrid').jqGrid('editRow', index, true, function(rowId) {
//when the user edits the row, query for all the seat types and fill in the list
jQuery.ajax({
url: '/getalltheseats',
complete: function (allSeats, stat) {
var list = $('#cargrid').find('tr[id="' + rowId + '"] td[is-seat-list="1"] select');
var $list = $(list);
//add the all seat types to the list, checking the ones that this car currently has selected
_.each(allSeats, function(seat) {
var selected = '';
if(curValues['Seats'].indexOf(seat.ID) !== -1) //<-- what do I do here??
selected = 'selected';
$list.append($('<option ' + selected + '></option>').attr('value', seat.ID).text(seat.Name));
});
});
});
});
},
The important line is
if(curValues['Seats'].indexOf(seat.ID) !== -1)
I have the value of the row but it only contains the seat name, not the ID. The data returned from the ajax call contains each seat name and ID but the <option> elements don't contain the ID value so I don't know which ones to select in the list.
So the question is, what's the best way to make jqGrid store both the seat names and IDs so that when I create the list dynamically, I can check the <option>s for the seats that have been chosen for that car.
Note:
For various reasons the standard dataUrl and buildSelect features of jqGrid are not going to work for me, which is why I'm building the list on the fly in this manner.
First of all you need additionally add formatter: "select" and to populate ID values in Seats column during filling of the grid. The formatter: "select" will decode the IDs and the corresponding Name value will be displayed to the user.
If you would use more recent version of jqGrid the you can use beforeProcessing callback created for the purpose. It allows to include all different ID/Name pairs in the server response for filling of the grid. It allows you to fill the information needed for the formatter: "select" directly in the main server response. You don't need to load the information before creating the grid.
If you use retro version of jqGrid (3.8.1) then I hope that you can still use the following trick. You can define userdata part of the server response defined as function. The outer elements of the server response root, page, total, records and userdata will be processed before the processing the main part with all items. It allows you to modify editoptions.value before it will be processed by formatter: "select".
For example the response from the server can looks like
{
"page": 1,
"total": 20,
"records": 400,
"userdata": {
"seats": "29991:Composite;42713:Nappa leather;6421:Steel;2883:Wire mesh"
},
"rows": [
{
"year": 2007,
"model": "Toyota/Camry",
"body": "Sedan",
"seats": "29991,6421"
},
{
"year": 2057,
"model": "BMW/Series 4",
"body": "Sedan",
"seats": "6421,2883"
}
]
}
Inside of jsonReader you can define userdata which set userdata.seats as value of editoptions. You can use setColProp method for example to do this.
In the way you will be able to implement all your requirements.
I have a JQGrid that groups together certain rows. I use group to define what rows should grouped together, so for example, if there are three 2s, it groups all 2s together. However it's possible there could be only one 2, in which case I wouldn't want it grouped, i.e. having the row under a group.
My question is, is it possible to have the grouping only be applied to certain rows and leave others alone?
Below is what I currently have:
colNames:['group', 'Description', 'File Sent to Customer', 'Date/Time', 'ATS', '# of Bib Records', '# of Items', 'Customer DB', 'Customer ID'],
colModel:[
{name:'group', index:'group'},
{name:'description', index:'description'},
{name:'fileSent', index:'fileSent', width:150},
{name:'date', index:'date', width:160},
{name:'ats', index:'ats', width:100},
{name:'bibRecords', index:'bibRecords', width:100},
{name:'items', index:'items', width:100},
{name:'customerDB', index:'customerDB', width:240},
{name:'customerID', index:'customerID', width:150}
],
grouping:true,
groupingView : {
groupField : ['group'],
groupColumnShow : [false],
groupText : [''],
groupCollapse : true,
groupOrder: ['desc']
},
I find your question interesting. So I wrote the solution which shows instead of the standard grouping (see the starting demo)
the following:
The corresponding code is not so complex:
loadComplete: function () {
var i, groups = $(this).jqGrid("getGridParam", "groupingView").groups,
l = groups.length,
idSelectorPrefix = "#" + this.id + "ghead_0_";
for (i = 0; i < l; i++) {
if (groups[i].cnt === 1) {
// hide the grouping row
$(idSelectorPrefix + i).hide();
}
}
}
It uses one level grouping, but it can be changed in the same way to the multilevel grouping.
One warning about the resulting grid: you should be careful with sorting of the grid. The problem is that jqGrid sort the rows inside of the group only. So the above rows with hidden grouping headers seems be out of sorting process.
I have built a dojo 1.5 datagrid + dojox.data.JsonRestStore. When the grid renders I can see the "carrot" that shows that sorting has fired and is on defaulting the right column. However, the content of the column(string values - field: 'projectShortName',...see code below) are not actually sorted. Hitting the descending/ascending button doesn't change the order or the rows. They are essentially locked in. I am not sure why?
I have column sorting turned off for certain columns and on for others using the canSort(). I only have formatters for calls with columns that have the sort turned OFF. I have tried making all columns sortable or only just the one that I really wanted. No dice.
Here is the layout/grid code:
var layout = [{
field: '_item',
name: ' ',
formatter: selectFormatter,
width: '25px'
},
{
field: 'projectName',
name: 'Project Name',
width: '325px'
},
{
field: 'projectShortName',
name: 'Short Name',
width: '80px'
},
{
field: 'projectAreaName',
name: 'RQM Project Area',
width: '175px'
},
{
field: '_item',
name: 'Test Guide Status',
width: '190px',
formatter: testCaseGenerationOptionFormatter
},
{
field: 'projectOwner',
name: 'Owner',
width: '140px'
},
{
field: 'projectCreationTime',
name: 'Created Date',
width: '100px'
},
{
field: 'projectLastUpdateTime',
name: 'Last Modified Date',
width: '120px'
}];
dojo.empty(dojo.byId('workspaceGridContainer'));
if (dijit.byId("projectGrid")) {
dijit.byId("projectGrid").destroyRecursive();
}
// Create a new grid:
var grid = new dojox.grid.DataGrid({
id:'projectGrid',
onHide: dojo.hitch(this, function() {
dijit.byId("projectGrid").destroyRecursive();
}),
store: jsonStore,
clientSort: true,
autoHeight: true,
//sortInfo: "-2",
selectionMode: 'single',
rowsPerPage: '100',
structure: layout
},document.createElement('div'));
dojo.byId("workspaceGridContainer").appendChild(grid.domNode);
// Call startup, in order to render the grid:
grid.startup();
//var test = grid.setSortInfo(obj);
// Prevent sorting on column 1
grid.canSort = function(col){ if((Math.abs(col) == 1) || (Math.abs(col) == 5) || (Math.abs(col) == 6) || (Math.abs(col) == 7) || (Math.abs(col) == 8)) { return false; } else { return true; } };
var index = grid.getSortIndex();
if(index!=2) {
if(grid.canSort(2)){
grid.setSortIndex(2, false);
}
}
As you can see commented out I have tried sortInfo as well. Any advice would be appreciated!
-Doug
You may be using the wrong comparison operator. The dojo documentation uses the strict equal '===' whereas you only use the equal '=='. This causes problems in js, especially when you're comparing a literal, i.e. '1' with an object: 'Math.abs(col). The official grid.canSort method should be coded as follows:
function canSort(col){ return Math.abs(col) === 2;}
Note Mozilla's description of the equal operator, and the type conversion js uses to resolve different data types:
https://developer.mozilla.org/en/JavaScript/Reference/Operators/Comparison_Operators
Equal (==) - If the two operands are not of the same type, JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible; else if either operand is a string, the other operand is converted to a string if possible. If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.