Sorting column with select elements changes the table DOM from select/html to static text for cells
Sorting column with select elements changes the table DOM from select/html to static text for cells
I am using DataTables 1.9.3 for my table.
I am using multi-filtering with a custom filtering plugin for some columns with select elements.
I'm also having a custom plugin for sorting my select columns.
My problem is that when I first sort my column and then filter it, it doesn't work. Analyzing aData in the filter function before sorting, I can see that the it contains the entire select (actually form) element. After I have performed the first sorting the aData contains the selected text only, not the entire form/select. Hence, my custom filtering function doesn't work the second time.
How can I make sure that the aData still contains the entire select/form so my custom plugins works after the first sorting?
My filtering plug-in:
[code]$.fn.dataTableExt.afnFiltering.push(
function( oSettings, aData, iDataIndex ) {
console.log(aData[1]);
var ret = true;
//Loop through all input fields i tfoot that has class 'sl_filter' attached
$('tfoot .sl_filter').each(function(i, obj){
//$(this) can be used. Get the index of this colum.
var i2 = $("tfoot input").index($(this));
i2 = oTable.fnVisibleToColumnIndex(i2);
//Create regexp to math
var r = new RegExp($(this).val(), "i");
//HTML does not get updated when changing value in select, hence searching for :selected return old value
//DataTables stores the DOM object oSettings. Hence, get the object and extract the text for the selected value.
var tr = oSettings.aoData[ iDataIndex ].nTr;
var id = $(aData[i2]).attr('id');
//Get the text
var str = "";
var value = "";
if($(aData[i2]).is("form")){
value = $("#" + id + " select", tr).val();
str = $("#" + id + " select option[value='" + value + "']", tr).text();
}else{
value = $("#" + id, tr).val();
str = $("#" + id + " option[value='" + value + "']", tr).text();
}
/*Test to see if there is a match or if the input value is the default
(the initial value of input before it has any fokus/text) */
if(r.test(str) || $(this).val()=="Search"){
//Return true only exits this function
return true;
}else{
/*Return false returns both function an .each. Retain 'false' in a variable scoped
to be reached outside the .each */
ret = false;
return false;
}
});
//Return true or false
return ret;
}
); [/code]
My sort plugin:
[code]$.fn.dataTableExt.afnSortData['dom-select'] = function ( oSettings, iColumn, iColumnVis){
iColumn = oSettings.oApi._fnColumnIndexToVisible( oSettings, iColumn );
var aData = [];
$( 'td:eq('+iColumn+') select', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
aData.push( $.trim($(":selected", this).text()));
} );
return aData;
};[/code]
It seems like the sort plugin is not only sorting the table but also updating the actual dom for the table.
I am using multi-filtering with a custom filtering plugin for some columns with select elements.
I'm also having a custom plugin for sorting my select columns.
My problem is that when I first sort my column and then filter it, it doesn't work. Analyzing aData in the filter function before sorting, I can see that the it contains the entire select (actually form) element. After I have performed the first sorting the aData contains the selected text only, not the entire form/select. Hence, my custom filtering function doesn't work the second time.
How can I make sure that the aData still contains the entire select/form so my custom plugins works after the first sorting?
My filtering plug-in:
[code]$.fn.dataTableExt.afnFiltering.push(
function( oSettings, aData, iDataIndex ) {
console.log(aData[1]);
var ret = true;
//Loop through all input fields i tfoot that has class 'sl_filter' attached
$('tfoot .sl_filter').each(function(i, obj){
//$(this) can be used. Get the index of this colum.
var i2 = $("tfoot input").index($(this));
i2 = oTable.fnVisibleToColumnIndex(i2);
//Create regexp to math
var r = new RegExp($(this).val(), "i");
//HTML does not get updated when changing value in select, hence searching for :selected return old value
//DataTables stores the DOM object oSettings. Hence, get the object and extract the text for the selected value.
var tr = oSettings.aoData[ iDataIndex ].nTr;
var id = $(aData[i2]).attr('id');
//Get the text
var str = "";
var value = "";
if($(aData[i2]).is("form")){
value = $("#" + id + " select", tr).val();
str = $("#" + id + " select option[value='" + value + "']", tr).text();
}else{
value = $("#" + id, tr).val();
str = $("#" + id + " option[value='" + value + "']", tr).text();
}
/*Test to see if there is a match or if the input value is the default
(the initial value of input before it has any fokus/text) */
if(r.test(str) || $(this).val()=="Search"){
//Return true only exits this function
return true;
}else{
/*Return false returns both function an .each. Retain 'false' in a variable scoped
to be reached outside the .each */
ret = false;
return false;
}
});
//Return true or false
return ret;
}
); [/code]
My sort plugin:
[code]$.fn.dataTableExt.afnSortData['dom-select'] = function ( oSettings, iColumn, iColumnVis){
iColumn = oSettings.oApi._fnColumnIndexToVisible( oSettings, iColumn );
var aData = [];
$( 'td:eq('+iColumn+') select', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
aData.push( $.trim($(":selected", this).text()));
} );
return aData;
};[/code]
It seems like the sort plugin is not only sorting the table but also updating the actual dom for the table.
This discussion has been closed.
Replies
[code]str = $('td:eq(' + i2 + ') option:selected', oSettings.aoData[ iDataIndex ].nTr).text();[/code]
The reason is that aData can be outdated compared to the dom (aoData).
When doing that I could also make my custom filtering function a bit more light:
[code]$.fn.dataTableExt.afnFiltering.push(
function( oSettings, aData, iDataIndex ) {
var ret = true;
//Loop through all input fields i tfoot that has class 'sl_filter' attached
$('tfoot .sl_filter').each(function(i, obj){
//$(this) can be used. Get the index of this colum.
var i2 = $("tfoot input").index($(this));
//Create regexp to math
var r = new RegExp($(this).val(), "i");
//Get the text
var str = $('td:eq(' + i2 + ') option:selected', oSettings.aoData[ iDataIndex ].nTr).text();
/*Test to see if there is a match or if the input value is the default
(the initial value of input before it has any fokus/text) */
if(r.test(str) || $(this).val()=="Search"){
//Return true only exits this function
return true;
}else{
/*Return false returns both function an .each. Retain 'false' in a variable scoped
to be reached outside the .each */
ret = false;
return false;
}
});
//Return true or false
return ret;
}
); [/code]