fnUpdate recursion causes error when the row's data object contain an object/array for a column

fnUpdate recursion causes error when the row's data object contain an object/array for a column

dmzdmz Posts: 2Questions: 0Answers: 0
edited November 2011 in Bug reports
Bug on function: this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )

The function above seems to not handle the case when your data for a column is an array or object and that object or array contains another array of values. It will try to update the row with the child array instead of updating the column with the child array. A simple fix to this would be to remove the recursion by doing one of the following:
Once you know you have an object or array for a whole row then loop through a different call to a helper function that updates only the specified column.
Another possible fix is to place an additional condition around the section detecting the object or array. The condition would be that if a column is specified don't do row updates because that means the input says to update a specific column not a row.

This may have arisen out of an unusual setup so a justification and details of how this situation manifested itself follows. The data table is based on an object and the columns are called out via aoColumns with mDataProp. One of the columns contains an array of objects. This column is hidden but searchable via an ofnSearch with a custom type. The column will show when the details section is expanded similar to the one in the examples. The array in the column data is rendered at the time more details is clicked. The reason for having an object is to allow for easier GSON based ajax submission when changes to the row occur. Using fnRender to render it properly before fnOpen breaks the ajax submission because it modifies the data object backing the row.

Replies

  • allanallan Posts: 63,689Questions: 1Answers: 10,500 Site admin
    Hi dmz,

    Interesting one. Have you tried the DataTables nightly ( http://datatables.net/download ) with this - I remember fixing a similar issue before. If that doesn't fix the problem, might you be able to post a link to your example with the problem or show us an example of the JSON you are using and the initialisation code.

    Thanks,
    Allan
  • dmzdmz Posts: 2Questions: 0Answers: 0
    edited November 2011
    I just tried build 1.8.3.dev. It seems to have the same issue. The section of code I mention (ln 1941-1994) seems unchanged. Here is a simple setup case.

    Below is some example code that causes the error. This works with the zero configuration example in jsbin. Click the button to cause the error to occur. The alert that pops up is a symptom of the problem. However if you debug through the code you will see that when it gets to the 5th column (i=4 on line 1965) it will call fnUpdate again but now the mData is an array of data. This pass it matches condition on ln 1948 for isArray. Now it tries to update the row with the columns array data which is not what is intended. Instead The column should have been updated with the array object.

    Notice that the initial render seems to behave as expected. It simply inserts the column data even if it is an array or object. The error only occurs when calling the fnUpdate.

    [code]
    $(document).ready(
    function() {
    var table = $('#example').dataTable({
    "sAjaxSource" : "",
    "fnServerData" : init,
    "aoColumns" : [ {
    "mDataProp" : "engine"
    }, {
    "mDataProp" : "browser"
    }, {
    "mDataProp" : "platform"
    }, {
    "mDataProp" : "version"
    }, {
    "mDataProp" : "css",
    "sType" : "array",
    "bSortable" : false
    } ]
    });

    $.fn.dataTableExt.ofnSearch['array'] = function(sData) {
    var result = "";
    for ( var i in sData) {
    result += sData[i] + " ";
    }

    return result;
    };

    function init(sSource, aoData, fnCallback) {
    fnCallback({
    "aaData" : [ getData(1), getData(2) ]
    });
    }

    function getData(i) {
    var data = {
    "engine" : "engine" + i,
    "browser" : "browser" + i,
    "platform" : "platform" + i,
    "version" : "version" + i,
    "css" : [ "search a" + i, "search b" + i ]
    };
    return data;
    }

    var button = $("Cause error with fnUpdate").click(
    function() {
    table.fnUpdate(getData(3), 0);
    });
    button.insertBefore(table);
    });
    [/code]
  • allanallan Posts: 63,689Questions: 1Answers: 10,500 Site admin
    Hi dmz,

    That's awesome - thanks very much for the test case. I've just committed a change to DataTables which is now in the nightly and takes this kind of situation into account: http://live.datatables.net/ayaroz/2/edit .

    You are absolutely correct that the issue is caused by the recursion - basically fnUpdate was seeing the inner array and getting itself all confused. So the fix is to let fnUpdate know that it is being called recursively.

    Regards,
    Allan
This discussion has been closed.