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

nicsoftnicsoft Posts: 37Questions: 0Answers: 0
edited August 2012 in General
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.

Replies

  • nicsoftnicsoft Posts: 37Questions: 0Answers: 0
    One must access the data for the table like this:

    [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]
This discussion has been closed.