jquery - property - DataTables ordena cadenas en lugar de numéricas
name datatable (4)
Estoy usando jquery.datatables para mostrar los números en las columnas de datatables. Los números están formateados para tener espacios entre miles de unidades (como 123 456 789
). Lamentablemente, este formato numérico provoca una clasificación de cadenas en lugar de una clasificación de números (ver la captura de pantalla al final de esta pregunta).
He identificado eso:
-
function _fnSort(oSettings, bApplyClasses) {
es la función central para la clasificación. - En esta función, se utiliza el enfoque de clasificación de funciones dinámicas (el ejecutado si
if (!window.runtime) {
es verdadero) Las funciones de clasificación de cadena utilizadas son las dos funciones siguientes.
/* * text sorting */ "string-asc": function(a, b) { var x = a.toLowerCase(); var y = b.toLowerCase(); return ((x < y) ? -1 : ((x > y) ? 1 : 0)); }, "string-desc": function(a, b) { var x = a.toLowerCase(); var y = b.toLowerCase(); return ((x < y) ? 1 : ((x > y) ? -1 : 0)); },
Mi conocimiento en javascript es bastante pobre, ¿cuál sería el mejor enfoque aquí?
- Modifique la función de clasificación de cadenas para detectar el número de casos formateados y haga la comparación (supongo que sería bastante lento en un conjunto de datos grande).
- Proporcionar una función de clasificación numérica dedicada para miles de números formateados ? En ese caso
- ¿Cómo codificaría eso?
- ¿Cómo podría indicarle a la función de clasificación de núcleo que use esta función especial de clasificación numérica?
Así es como se ve la clasificación por ahora:
Para ordenar este tipo de valores, puede usar esta función de clasificación:
var sortFunction=function(a, b){
var ia = parseInt(a.split('' '').join(''''), 10);
var ib = parseInt(b.split('' '').join(''''), 10);
return ia-ib;
};
Prueba :
var data = [''3 333'', ''100 333'', ''22 000'', ''1 333''];
console.log(data.sort(sortFunction));
Con una cantidad razonable de valores, esto será lo suficientemente rápido. No intente enriquecer los datos si no detecta problemas de rendimiento.
EDITAR:
De hecho, la documentación propone una función de clasificación apropiada (similar):
jQuery.extend( jQuery.fn.dataTableExt.oSort, {
"formatted_numbers-pre": function ( a ) {
a = (a==="-") ? 0 : a.replace( /[^/d/-/.]/g, "" );
return parseFloat( a );
},
"formatted_numbers-asc": function ( a, b ) {
return a - b;
},
"formatted_numbers-desc": function ( a, b ) {
return b - a;
}
} );
Después de haber agregado esta extensión, solo tiene que configurar el tipo de su columna.
Ok, después de mucha búsqueda, encontré soluciones alternativas. La solución propuesta por dystroy y Allan Jardine es ciertamente más limpia. Pero implica tocar el HTML y, en mi caso , tocar el cuadro de mensaje complicado provocado por HTML como este a continuación.
Así que mi solución es simplemente tocar el algoritmo de clasificación de cadenas de javascript, para alternar entre los casos numéricos y textuales. Desearía que pudiera ser más limpio usando algo como isDigit(sa.charAt[0])
pero simplemente no funciona a pesar de todos mis intentos. Al menos esta solución funciona y no implica ningún costo de rendimiento notable:
/*
* text + integer sorting
*/
"string-asc": function(a, b) {
var sa = a.toString();
if(sa.length > 0) {
// Don''t know why, isDigit(sa.charAt[0]) doesn''t work??
var ca = sa.substring(0,1);
if(ca === "0" || ca === "1" || ca === "2" || ca === "3" || ca === "4" || ca === "5" || ca === "6" || ca === "7" || ca === "8" || ca === "9") {
var x1 = parseInt(a.split('' '').join(''''), 10);
var y1 = parseInt(b.split('' '').join(''''), 10);
return x1 - y1;
}
}
var x = a.toLowerCase();
var y = b.toLowerCase();
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
},
"string-desc": function(a, b) {
var sa = a.toString();
if(sa.length > 0) {
var ca = sa.substring(0,1);
if(ca === "0" || ca === "1" || ca === "2" || ca === "3" || ca === "4" || ca === "5" || ca === "6" || ca === "7" || ca === "8" || ca === "9") {
var x1 = parseInt(a.split('' '').join(''''), 10);
var y1 = parseInt(b.split('' '').join(''''), 10);
return y1 - x1;
}
}
var x = a.toLowerCase();
var y = b.toLowerCase();
return ((x < y) ? 1 : ((x > y) ? -1 : 0));
},
Para cualquiera que esté leyendo esto y quiera la respuesta completa para el espacio entre números:
jQuery.extend( jQuery.fn.dataTableExt.oSort, {
"formatted_numbers-pre": function ( a ) {
a = (a===" ") ? 0 : a.replace( /[^/d/-/.]/g, "" );
return parseFloat( a );
},
"formatted_numbers-asc": function ( a, b ) {
return a - b;
},
"formatted_numbers-desc": function ( a, b ) {
return b - a;
}
} );
$(''.myTable'').DataTable({
"columnDefs": [
{ "type": "formatted_numbers", "targets": 4 }
],
});
}
Simplemente configure el punto decimal cuando construya la DataTable de la siguiente manera:
var main_table = $(''#main_list'').DataTable({
ajax: {
url: "/api/your/data",
dataSrc: ''''
},
columns: [
{ data: "Col1" },
{ data: "Col2" },
{ data: "Col3" },
{ data: "Col4" }
],
language: {
/* -----> */ "decimal": ",", // <---------
"emptyTable": "Keine Daten in der Tabelle verfügbar",
"info": "Anzeigen von _START_ bis _END_ von _TOTAL_ Einträgen",
"infoEmpty": "Anzeigen von 0 bis 0 von 0 Einträgen",
"infoFiltered": "(filtriert von_MAX_ Gesamteinträge)",
"infoPostFix": "",
/* -----> */ "thousands": ".", // <---------
"lengthMenu": "_MENU_ Einträge anzeigen",
"loadingRecords": "Laden...",
"processing": "Verarbeitung...",
"search": "Suche:",
"zeroRecords": "Keine passenden Datensätze gefunden",
"paginate": {
"first": "Erste",
"last": "Letzte",
"next": "Nächste",
"previous": "Vorherige"
},
"aria": {
"sortAscending": ": aufsteigend sortieren",
"sortDescending": ": absteigend sortieren"
}
},
columnDefs: [
{//set german formatting
render: function (data, type, row) {
return formatDE(data,2);
},
targets: [2, 4, 5]
},
{
render: function (data, type, row) {
return formatDE(data,0);
},
targets: [3]
}
],
pageLength: 50});
Si profundiza más en jquery.dataTables.js
, encontrará que tienen una función que determina el tipo de valor de cada columna y capta el formato