DataTables sort currency - sorting

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

Related

In my Datatable, I have a simple column containing only simple strings but it's not sorting correctly

I have a really simple Datatable. Every columns are sorting correctly except one. This columns contain only text (string).
Here's the order I get when I sort the column:
À publier,
Retiré temporairement,
Retiré - Rejet
Nouveau.
Here's the code for the Datatable, as you can see, it's quite simple.
var peutModifier = $('#hdnPeutModifier').val();
if (peutModifier !== 'undefined' && peutModifier === 'True') {
colonneAvecTriDesactive = [0, -1]; // Tri désactivé sur première et dernière colonne.
} else {
colonneAvecTriDesactive = [-1]; // Tri désactivé sur dernière colonne.
}
$('#DataTablePublication').DataTable({
search: false,
bFilter: false,
pageLength: 100,
lengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
columnDefs: [
{ orderable: false, targets: colonneAvecTriDesactive }
],
order: [],
language: {
paginate: {
first: "Premier",
last: "Dernier",
next: "Suivant",
previous: "Précédent"
}
}
});
I checked and the column contains only strings, also, I have not set any trigger on the column sorting and I don't have any errors in my browser.
Does someone have an idea about this problem?
This looks like you have sorted your column in reverse alphabetical order - which is why À appears first (since À follows z, using default codepoint sorting).
To use language-sensitive sorting, i.e. the sort order that you would expect to find in a dictionary (where église follows eagle, not zebra), you can use the DataTables internationalization plug-in.
Steps to use:
Add the library to the <head> section of your page. You can use a CDN for this:
<script src="https://cdn.datatables.net/plug-ins/1.11.0/sorting/intl.js"></script>
Initialize the plug-in in your script, before you create your DataTable:
$.fn.dataTable.ext.order.intl();
You can also provide an explicit locale if you want to:
$.fn.dataTable.ext.order.intl('fr');
There are various additional configuration options described here.

Adjust DataTables ordering

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/

bootstrap-typeahead's displayfield using multiple values

I'm sorry if this is a duplicate question but I do not understand the answers of other people. I'm using Twitter Bootstrap Ajax Typeahead Plugin (https://github.com/biggora/bootstrap-ajax-typeahead/) to search emails from data that comes from an SQL query. This is the code I use with a php file, where I use people's emails as valueField and people's names as displayField and it works well.
inputSearch.typeahead({
ajax: {
url: urlAjax + '?requete=rechercheannuaire',
displayField: "description",
valueField: "id",
triggerLength: 2,
method: "get",
loadingClass: "loading-circle",
preProcess: function(data){
if(data.type === "error")
{
return false;
}
return data.datas;
}
},
onSelect: function(data){
//alert("assez tot");
data.text = data.value;
//console.log(data);
$("#chercherinvite").val(data.text);
return data;
}
});
The problem is that I have to be able to search "Dujardin" as well as "Du Jardin" and I cannot find a way to assign multiple values to displayField. If someone could explain how typeahead works, I'd be thankfull, I don't understand the documentation.
According to the plugin documentation, you cannot assign multiple values to the displayField option. However, it is possible for you to re-write events.
After a quick lookup into the source code of bootstrap-ajax-typeahead, we can figure out that the "matcher" event is used as the filter for displaying - or not - values to the user.
To allow to match both "Du jardin" and "Dujardin", we have to manipulate strings. Here, I suggest you to :
Remove any diacritic character
Remove any non-word character (all except [A-Za-z0-9_])
Remove any underscore
Set the string to lowercase
To do #1, I suggest you to use this fantastic script by rdllopes.
I wrote a POC. Here is the JSON source (called "source.json"):
[
{ "id": 1, "name": "jdupont#example.com - Jean Du Pont"},
{ "id": 2, "name": "jdupont2#example.com - Jean Dupont"},
{ "id": 3, "name": "jdupont3#example.com - Jéan Dupônt"},
{ "id": 4, "name": "mbridge#example.com - Michel Bridge"}
]
And here is the script that I used for matching elements :
$('#search').typeahead({
// Our source is a simple JSON file
ajax: 'source.json',
// Display field is a list of names
displayField: 'name',
// And value field a list of IDs
valueField: 'id',
matcher: function(item)
{
// For both needle and haystack, we :
// 1. Remove any diacritic character
// 2. Remove any non-word character (all except [A-Za-z0-9_])
// 3. Remove any underscore
// 4. Set the string to lowercase
var needle = removeDiacritics(this.query).replace(/[^\w]/gi, '').replace('_', '').toLowerCase();
var haystack = removeDiacritics(item).replace(/[^\w]/gi, '').replace('_', '').toLowerCase();
// Does the needle exists in haystack?
return ~haystack.indexOf(needle);
}
});

jQuery dataTables : Clicking thead should sort descending and then ascending for all columns

I am trying to change the default sorting direction. The default order is ascending and then descending. I am trying to reverse it.
The sorting direction should be independent and should apply to all the columns( Number of columns vary with different tables ) The script I have to initiate datatable is generic.
Sorting should only apply on click.
I found few examples but they are column specific https://datatables.net/examples/advanced_init/sort_direction_control.html
Here is my script
jQuery(function($) {
$(".datatable").dataTable({
"paging": false,
"searching": false,
"info": false,
"orderCellsTop": true
});
});
All options and settings has default values defined in the internal DataTable.defaults object. This object is available for altering through $.fn.dataTable.defaults. This is poorly documented on the website, but very well documented in the code. Open a none minified jquery.dataTables.js and search for DataTable.defaults.
To reverse the default ordering for all columns, so it becomes desc, asc :
$.fn.dataTable.defaults.column.asSorting = ['desc', 'asc'];
To set the initial ordering for the first column to desc
$.fn.dataTable.defaults.aaSorting = [[0,'desc']];
Likewise you can simply alter the defaults so you not need to set any generic options in your dataTable() at all :
$.fn.dataTable.defaults.bPaginate = false; //paging: false
$.fn.dataTable.defaults.bFilter = false; //searching: false
$.fn.dataTable.defaults.bInfo = false; //info: false
$.fn.dataTable.defaults.bSortCellsTop = true; //orderCellsTop: true
see demo -> http://jsfiddle.net/f31pncb4/
You can do it while initializing:
jQuery(function ($) {
$(".datatable").dataTable({
"paging": false,
"searching": false,
"info": false,
"orderCellsTop": true,
aoColumnDefs: [
{
orderSequence: ["desc", "asc"],
aTargets: ['_all']
}
]
});
});
Richard's answer above works but is the legacy approach. The syntax for current versions is similar and a bit simpler:
var myTable = $('table').DataTable({
"columnDefs": [
{
"orderSequence" : [ "desc", "asc" ],
"targets" : "_all"
}
]
});
Slightly off topic but note capital "D" in DataTable() which returns an api instance instead of a jquery object. This is important since doing it this way allows you easier access to the api after initialization.
Extending the #Eaten by a Grue's answer, if we want, we can use the same orderSequence API to reverse the sort order using HTML only.
Under the <thead>, we can change the <th> as follows:
<th data-order-sequence='[ "desc", "asc" ]'>Amount</th>

JqGrid custom formatter with custom parameter

I have a question about custom formatters.
What I try to achieve is a currencyFormatter just for the amount with Locale sent by the server, when locale is not define or supported fall back to British English.
Something like this:
function currencyFmatter(cellvalue, options, rowdata) {
return new Intl.NumberFormat([locale, "en-GB"], {minimumFractionDigits: 2, maximumFractionDigits: 2}).format(cellvalue);
}
My problem is how to pass my variable locale to the formatter, I’m pretty sure it has to be a way to do it but right now I don’t see it.
Thanks
It's an interesting question! There are many ways to implement your requirements.
1) you can extend your input data returned from the server with additional information which specify the locale of data. For example you can returns "de-DE:10.000,04" instead of "10.000,04" which represent 1000.04 formatted in German locale (where , will be used as the decimal separator and . used as the thousands separator). It allows you to use cellvalue.split(":") to get array ["de-DE", "10.000,04"] with the locale of the number and the number itself
function currencyFmatter(cellvalue, options, rowdata) {
var data;
if (typeof cellvalue === "string") {
data = cellvalue.cellvalue.split(":");
if (data.length === 2) {
return new Intl.NumberFormat([data[0], "en-GB"], {
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(data[1]);
}
}
return cellvalue;
}
Alternatively you can place the information about locale of the number in separate field (for example numLocale) of the input data and use something like rowdata.numLocale (or rowdata[12] depend on the input format of the JSON data) to access the locale.
2) It could be that all the data returned from the server will be in the same format. In the case it would be not the best way to prepend all numbers with the same prefix "de-DE:". What you can do for example is to extend the data returned from the server with additional field. For example you can use
{
"total": "12",
"page": "1",
"records": "12345",
"localOfNumbers": "de-DE",
"rows" : [
...
]
}
You can access the custom localOfNumbers field inside of beforeProcessing callback. It's very practical callback. It allows you to pre-process the data returned from the server before the data will be processed by jqGrid. I recommend you to read the answer and this one for more code example. What you can do for example is to save localOfNumbers value in some new option of jqGrid (see the answer for more details). Let us you want to have an option gridLocale for the goal. Then you can do something like the following:
beforeProcessing: function (data) {
if (typeof data.localOfNumbers === "string") {
$(this).jqGrid("setGridParam", {gridLocale: data.localOfNumbers});
}
}
To access the new gridLocale option you can use
function currencyFmatter(cellvalue, options, rowdata) {
var locale = $(this).jqGrid("getGridParam", "gridLocale"); // this.p.gridLocale
}
3) You can consider to save the information about the locale as column property instead of usage one common gridLocale grid option. To do this you can define the column in colModel like below
{ name: 'col2', width: 200, formatoptions: { colLocale: "en-IN" },
formatter: function (cellvalue, options, rowdata) {
// options.colModel.formatoptions.colLocale get you the value
}
One can set the property of formatoptions.colLocale inside of beforeProcessing too. You can use
{
"total": "12",
"page": "1",
"records": "12345",
"localOfColumns": {
"col2": "de-DE",
"col5": "en-IN"
},
"rows" : [
...
]
}
and
beforeProcessing: function (data) {
if ($.isPlainObject(data.localOfColumns)) {
if (typeof data.localOfColumns.col2 === "string") {
$(this).jqGrid("setColProp", "col2", {
formatoptions: { colLocale: data.localOfColumns.col2 }
});
}
if (typeof data.localOfColumns.col5 === "string") {
$(this).jqGrid("setColProp", "col5", {
formatoptions: { colLocale: data.localOfColumns.col5 }
});
}
}
}
I'm sure that one can suggest even more ways to implement your requirements.

Resources