Adjust DataTables ordering - sorting

I have the following data I'm passing to a DataTables table:
data = [{'state': 'Baseline', 'contact': 'Johnny', 'years_active': 10},
{'state': '1', 'contact': 'Rachel', 'years_active': 10},
{'state': '2', 'contact': 'Steve', 'years_active': 8}]
The table has three columns: state, contact, and years_active. When I sort on the state column, the row with state='Baseline' is at the bottom of the table. Is there any way to adjust the sorting mechanism so this row will be on top?
Maybe convert Baseline to '0' in the background or maybe define character values as less then number values?

You can control the sort value in the columns render callback. The type argument defines what scope the returned value will be used for, i.e filter, sort, display. With the magic of the || operator you can return -1 when the column is about to be sorted, and the value is not a number :
columns: [
{ data: 'state',
render: function(data, type) {
if (type == 'sort') {
return parseInt(data) || -1
}
return data
}
},
{ data: 'contact' },
{ data: 'years_active' }
]
see demo -> http://jsfiddle.net/721hdxa5/

Related

jqgrid reading form element value and dynamically changing select option

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();

Custom column filter on a formatted column

I need help using a custom column filter for handling JS objects.
I have a slickgrid table where the values in one column are JS object:
[
{ id: "1234", text: "Batman"},
{ id: "2345", text: "Robin"}
]
I use a custom formatter to smash the object into a string:
// convert [{id:string, text:string}...] to string
const optionFormatter: Formatter = (row, cell, value, columnDef, dataContext: any) =>
value ? value.map(o => o.text).join(', ') : '';
Which displays in slickgrid as
Batman, Robin
my slickgrid options use gridmenu and enables column filtering:
this.gridOptions = {
enableGridMenu: true,
enableFiltering: true,
enableAutoResize: true,
enableColumnReorder: true
};
My columnDef enables filtering for this column:
{
id: 'owners',
name: 'Owners',
field: 'owners',
sortable: false,
formatter: optionFormatter,
filterable: true
}
Everything works if the value in the cell is a string, but the filter doesn't work if the cell is an object. I assume the filter is searching the pre-formatted value.
Is there a way to provide the column with a custom filter function that knows how to search the JS object for the query string? For example if I could just search the JSON.stringify(value), that would be good enough.
Alternatively, this answer describes how I could use the formatter to store the formatted text as a different string property in dataContext. If I do that, how do I specify which property to filter, seeing as it is a different property than the column field?
I found a workaround.
preprocess my data, calling JSON.stringify on all values that are objects:
flattenFeature(f: Feature): any{
var res = {};
for (var prop in f) {
res[prop] = (typeof f[prop] === 'object') ? JSON.stringify(f[prop]) : f[prop];
}
return res;
}
Then in my formatter, I parse the json, before formatting:
// convert [{id:string, text:string}...] to string
const optionFormatter: Formatter = (row, cell, value, columnDef, dataContext) =>
value ? JSON.parse(value).map(o => o.text).join(', ') : '';
This allows the standard string filter to search the stringify'd JSON

DataTables sort currency

Please help with live example, how to sort currency in format "34 566.00 ek." in DataTables script.
Here is JSFiddle example: http://jsfiddle.net/HEDvf/643/
$('#example').dataTable({
"aoColumns": [
null,
],
"aaSorting": [[ 0, "desc" ]],
"bStateSave": false,
"iDisplayLength": 50,
});
Have a look at the very extensive datatables documentation. There you will find simple solutions to almost all problems you will ever have with datatables. There are for example little plugin functions to add sorting support for currency columns.
An example based on what you got:
// add sorting methods for currency columns
jQuery.extend(jQuery.fn.dataTableExt.oSort, {
"currency-pre": function (a) {
a = (a === "-") ? 0 : a.replace(/[^\d\-\.]/g, "");
return parseFloat(a);
},
"currency-asc": function (a, b) {
return a - b;
},
"currency-desc": function (a, b) {
return b - a;
}
});
// initialize datatable and explicitly set the column type to "currency"
$('#example').dataTable({
"aoColumns": [{"sType": "currency"}],
"aaSorting": [[0, "desc"]],
"bStateSave": false,
"iDisplayLength": 50,
});
Links to the documentation:
Sorting: http://datatables.net/plug-ins/sorting#currency
Datatables is also able to automatically detect column types, but it gets a bit complicated with all the different formattings. Type-detection: http://datatables.net/plug-ins/type-detection#currency
I have no reputation enough to add a command to the answer of #Gigo. So I will post this as a answer.
If you use European currency format, a point '.' is used as thousand separator instead of a comma ','. So the sorting script won't work correctly because 1.000,00 is interpreted as ONE point ZERO
To get this fixed, change the regex to:
/[^\d\-\,]/g
Point changed to comma, now 1.000,00 will be interpreted as ONE THOUSAND point ZERO.
Might be a dirty solution but you can use it to remove number format (,) from the string as well
jQuery.extend(jQuery.fn.dataTableExt.oSort, {
"currency-pre": function (a) {
console.log("PRE "+a);
a = (a === "-") ? 0 : a.split(',').join('').replace(/[^\d\-\.]/g, "");
return parseFloat(a);
},
"currency-asc": function (a, b) {
console.log("ASC "+a);
return a - b;
},
"currency-desc": function (a, b) {
console.log("DESC "+a);
return b - a;
}
});

jqGrid text Sort Order

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.

Don't Group Single Rows in JQGrid

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.

Resources