Warning - added data does not match known number of columns

Warning - added data does not match known number of columns

mainstreetmarkmainstreetmark Posts: 9Questions: 0Answers: 0
edited September 2009 in General
I've had this since 1.5.0 (which is the earliest version i've used)

It goes like this:
- The table uses sAjaxSource, full_numbers, ...
- During development, I have a number of columns, say 4 columns.
- I add a fifth column, and reload the page.
- A JS dialog shows up with the above message, each time a row is drawn.

BUT, if I load this version in a different browser, it displays properly, leading me to believe it's some form of cookie-setting problem.

So, here's my digging:
- oSettings.aoColumns around line 1956 doesn't contain the new 5th column
- _fnAddColumn() used around line 4474 is in a loop only up to 4, because oInit.aoColumns is only 4 elements long, and bUseCols is set. nThs.length, at this point, contains the correct number of columns (5).
- line ~4096 oData.abVisCols.length is 4, not 5, and evidently, this showed up in 1.5.0b10
- line ~4037: var sData = _fnReadCookie( "SpryMedia_DataTables_"+oSettings.sInstance );

Evidently that cookie contains the "old" visibility array, and it isn't accounting for a change of columns between page displays. Perhaps the cookie needs to be reset if there's a change in column count.

At the very least, if that warning message pops, abort the loop that draws rows.

Replies

  • allanallan Posts: 63,498Questions: 1Answers: 10,470 Site admin
    Hi mainstreetmark,

    Interesting one! How about this for a possible fix - line 4472 (of 1.5.2):

    [code]
    var col = bUseCols ? oInit.aoColumns[i] : null;
    [/code]
    Replace it with:

    [code]
    var col = (bUseCols && oInit.aoColumns[i]!='undefined') ? oInit.aoColumns[i] : null;
    [/code]
    And hopefully that will fix the issue you are facing just now. I'm going to have a closer look at how this might be improved for future versions - but might get things working for you :-)

    Regards,
    Allan
  • mainstreetmarkmainstreetmark Posts: 9Questions: 0Answers: 0
    Not really. I had to additionally do this to 4469:

    for ( i=0, iLen= nThs.length ; i
  • allanallan Posts: 63,498Questions: 1Answers: 10,470 Site admin
    Oops - yup - that too :-)

    However, that probably means that you now can't have an empty element and have DataTables automatically create the TH elements for you. That might work for the case were you are using it, but breaks some other functionality that DataTables offers...

    Allan (lost in thought now...)
  • mainstreetmarkmainstreetmark Posts: 9Questions: 0Answers: 0
    Yeah, of course. I'm aware this is a hack instead of a solution.

    My previous solutions were to comment out that whole check in the first place, and just have a "broken" table. At least now, i have a working table, so I'm moving forward.
  • atcatc Posts: 14Questions: 0Answers: 0
    edited September 2009
    Hi Allan,

    I was having a similar problem with multiple dynamic tables sharing a URL; this thread solved the problem... mostly. The th elements are now the problem, as you mentioned above. I added some code to prep the page with an empty table with the correct number of th elements, like so:

    [code]




    <?php
    for ($i=1;$i<=$numCols+1;$i++) {
    echo "$i";
    }
    ?>

    <!---->


    <?php
    for ($i=1;$i<=$numCols+1;$i++) {
    echo "$i";
    }
    ?>




    [/code]

    (I get the $numCols based on a $matrixID). So the table now loads properly, but unfortunately my sClass, sTitle, and sType info gets lost along the way. Strangely, though, it preserves the sWidth.
    For example, I define the first column as
    [code]
    array('sTitle'=>'ID', 'sClass'=>'index', 'sWidth'=>'20px', 'sType'=>'numeric')
    [/code]
    but it shows up in the table as
    [code]
    ID
    [/code]

    Subsequent columns have more detailed info, which is important to the functioning of the rest of the page, e.g.
    [code]
    array('sTitle'=>$columnHeader, 'sClass'=>'editable abbr ls' . $lifestageID . ' mcol' . $mcolID, 'sType'=>'html');
    [/code]

    Is this something I'll have to address by further editing the main datatables.js? If so, could you possibly point me in the right direction? I'm afraid I'm in a bit over my head, so I'm a bit wary of diving in to the main body of code.

    Thanks again for a great tool, and for supporting it so well! Trying to figure out how to adapt DataTables for my project has taught me a lot about javascript & jquery, and I doubt I'd have been able to get so far if I'd chosen a different basis for the tables.

    Best,
    Alison
  • allanallan Posts: 63,498Questions: 1Answers: 10,470 Site admin
    Hi Alison,

    Sounds quite complicated! Could you probable provide a little more detail please? Specifically, I'm not clear on how your are initialising DataTables. Also - I presume you are using state saving as well? Is it just that the cookie is out of date and if you delete it, the problem goes away?

    Allan
  • atcatc Posts: 14Questions: 0Answers: 0
    Hi Allan,

    thanks for replying so quickly. I would point you to the site itself except it's on a password-protected server that I don't have authority to grant access to. Tried setting up a dummy version of the page, but it's got so many moving parts that proved too complicated. Anyway a lot of the back end is PHP that wouldn't be clear just looking at the site anyway, so I'll try to explain as clearly as I can:

    There are multiple different datasets (2 at the moment, quite a few more planned over time). The datasets share many column headings, so I've set the mysql database up with the following tables:

    matrices (includes matrixID, title)
    matrix_columns (includes mcolID, matrixID, columnID, sortnum)
    matrix_column_definitions (includes columnID, lifestageID, columnHeader)
    matrix_content (includes contentID, mcolID, mrowID)

    The data is called from the database with an .ajax call. As in the example in my earlier comment, each column is defined with a number of classes, including the mcolID, which is extracted to ID each th, and used along with the mrowID and a tab ID to add a contentID to each cell of the DB for purposes of editing/updating the database (with jeditable & tinymce).

    I've also implemented your fnClickAddRow, with limited success. I tried setting the SpryMedia_DataTables_currentreqs_clientscmsmatrix-dev_php cookie to null, also tried destroying it by setting the expiration in the past, but neither had the desired effect. There didn't seem to be any other datatables-generated cookies.

    Let me know if any of this is unclear. I really appreciated your help!

    Thanks,
    Alison
  • atcatc Posts: 14Questions: 0Answers: 0
    Here's my code for the initialization:

    [code]
    $.ajax({
    type: "GET",
    url: "/clients/data/matrix_json_dev.php",
    data: "mxID="+matrixID+"&statusID=1&t=1&editable=T",
    dataType: "text",
    success: function(data){
    var json = JSON.parse(data);
    var cols = json.aoColumns;
    numCols = cols.length;
    //alert(numCols+"cols"); // test
    oMatrix1 = $('#currentreqs').dataTable( {
    "bProcessing": true,
    "aaData": json.aaData,
    "aoColumns": json.aoColumns,
    "iDisplayLength": 10,
    "bStateSave": true,
    "bAutoWidth": false,
    "sPaginationType": "full_numbers",
    "sDom": '<"tableheader"lf><"tableinfo"i>r<"clear">t<"tablefooter"p><"clear">f',
    "fnDrawCallback": function() {
    //alert( 'DataTables has redrawn the table' );
    //
    rememberSettings();
    $('#progress').hide();
    // Apply the jEditable handlers to the table
    <!-- BOF jEditable/tinyMCE Part II -->

    $(function(){


    $('#foo').tinymce();

    $('#currentreqs tbody td.editable').editable('/clients/codelib/update_matrix.php', {
    "tooltip" : 'Double-click to edit...',
    "placeholder": '',
    "type" : 'mce',
    "submit" : 'Submit',
    "cancel" : 'Cancel',
    "cssclass" : 'expanding',
    //"style" : 'inherit',
    "indicator" : 'saving',
    "width" : '250px',
    "height" : '200px',
    //"height" : 'auto',
    "event" : 'dblclick',
    "callback": function( sValue, y ) {
    var aPos = oMatrix1.fnGetPosition( this );
    var theID = $(this).attr('id');
    //alert("sValue: " + sValue + "; theID: " + theID + "; aPos: " + aPos);
    oMatrix1.fnUpdate( sValue, aPos[0], aPos[1] );
    alert("update complete");
    },
    error: function (XMLHttpRequest, textStatus, errorThrown) {
    alert( "XMLHttpRequest: " + XMLHttpRequest );
    alert( "errorThrown: " + errorThrown );
    alert( "textStatus: " + textStatus );
    }
    } );

    });

    <!-- EOF jEditable/tinyMCE Part II -->

    $('#currentreqs thead tr').each( function() {
    var nThs = $('th', this);
    var thID;
    var mcolID;
    var colHeader;
    var cellClasses;
    var startPos;
    var stopPos;
    var tmpStr;
    var i = 1;
    //
    nThs.each( function() {
    cellClasses = $(this).attr('class');
    colHeader = $(this).text();
    $('#tab1foot'+i).text(colHeader);
    this.setAttribute('title',cellClasses);
    startPos = cellClasses.search('mcol'); //stringObject.search(searchstring)
    startPos = startPos + 4;
    tmpStr = cellClasses.substring(startPos); //stringObject.substring(start,stop)
    stopPos = tmpStr.search(' ');
    if (stopPos == -1) {
    mcolID = tmpStr;
    } else {
    mcolID = tmpStr.substring(0,stopPos);
    }
    thID = "col" + mcolID;
    this.setAttribute( 'id', thID );
    i++;
    //
    });
    //
    } );
    //
    $('#currentreqs tbody tr').each( function() {
    var nTds = $('td', this);
    var cellClasses;
    var startPos;
    var stopPos;
    var tmpStr;
    var contentID; // how to get it?
    var mrowID = $(nTds[0]).text();
    var mcolID;
    var tdID;
    //
    nTds.each( function() {
    cellClasses = $(this).attr('class');
    startPos = cellClasses.search('mcol'); //stringObject.search(searchstring)
    startPos = startPos + 4;
    tmpStr = cellClasses.substring(startPos); //stringObject.substring(start,stop)
    stopPos = tmpStr.search(' ');
    if (stopPos == -1) {
    mcolID = tmpStr;
    } else {
    mcolID = tmpStr.substring(0,stopPos);
    }
    tdID = "x" + mrowID + "y" + mcolID + "t" + 1;
    this.setAttribute( 'id', tdID );
    var tdText = $(this).text();
    });
    //
    } );
    //
    }
    } );
    //oMatrix1.fnSetColumnVis(0,0); // causes problems with updates -- ???
    //
    },
    error: function (XMLHttpRequest, textStatus, errorThrown) {
    alert( "XMLHttpRequest: " + XMLHttpRequest );
    alert( "errorThrown: " + errorThrown );
    alert( "textStatus: " + textStatus );
    }
    }); // ajax oMatrix1
    [/code]
  • allanallan Posts: 63,498Questions: 1Answers: 10,470 Site admin
    Hi Alison,

    Thanks very much for the code! One more thing would be quite useful - couple you possibly post an example of the JSON string that the serve sends back?

    There is one other thing that springs to mind - have you tried having DataTables automatically create the header element for you? (see this example http://datatables.net/examples/data_sources/js_array.html ). With this you can simply have an empty tags (i.e. remove the thead and tbody and any child elements) and DataTables will add then in based on the aoColumns information.

    Regards,
    Allan
  • atcatc Posts: 14Questions: 0Answers: 0
    Hi again,

    here's the sample JSON:

    [code]
    { "aaData":[["1","Apples","Kiwi<\/p>","Kumquat<\/p>","Guava<\/p>","Pomegranate<\/p>","Banana<\/p>","","","","","","","",""],["2","Oranges<\/p>","","","Peach<\/p>","","","","","","","","","",""]], "aoColumns": [{"sTitle":"ID","sClass":"index","bSearchable":false,"sWidth":"20px","sType":"numeric"},{"sTitle":"Test Col 2","sClass":"locked editable ls0 mcol51","sWidth":"80px","sType":"html"},{"sTitle":"Test Col 3","sClass":"editable abbr ls0 mcol52","sType":"html"},{"sTitle":"Test Col 4","sClass":"editable abbr ls0 mcol53","sType":"html"},{"sTitle":"Test Col 5","sClass":"editable abbr ls1 mcol54","sType":"html"},{"sTitle":"Test Col 10","sClass":"editable abbr ls3 mcol55","sType":"html"},{"sTitle":"Test Col 9","sClass":"editable abbr ls1 mcol56","sType":"html"},{"sTitle":"Test Col 7","sClass":"editable abbr ls1 mcol57","sType":"html"},{"sTitle":"Test Col 8","sClass":"editable abbr ls1 mcol58","sType":"html"},{"sTitle":"Test Col 6","sClass":"editable abbr ls1 mcol59","sType":"html"},{"sTitle":"Test Col 11","sClass":"editable abbr ls3 mcol60","sType":"html"},{"sTitle":"Test Col 12","sClass":"editable abbr ls3 mcol61","sType":"html"},{"sTitle":"Test Col 13","sClass":"editable abbr ls3 mcol62","sType":"html"},{"sTitle":"Test Col 14","sClass":"editable abbr ls3 mcol63","sType":"html"},{"sTitle":"Test Col 15","sClass":"last editable abbr ls0 mcol64","sType":"html"}] }
    [/code]

    Re the header element -- that's what I had it doing previously, but if I use the changes suggested above to the datatables.js code, I get an error message about missing th elements, so I had to build them in to the page.

    Best,
    Alison
  • allanallan Posts: 63,498Questions: 1Answers: 10,470 Site admin
    Hi Alison,

    Sorry for the delay in getting back to you about this - did you manage to get anywhere with it in the mean time?

    I've just tried the following code along with your json data above:

    [code]
    oMatrix1 = $('#example').dataTable( {
    "bProcessing": true,
    "aaData": json.aaData,
    "aoColumns": json.aoColumns,
    "iDisplayLength": 10,
    "bStateSave": true,
    "bAutoWidth": false,
    "sPaginationType": "full_numbers",
    "sDom": '<"tableheader"lf><"tableinfo"i>r<"clear">t<"tablefooter"p><"clear">f'
    } );
    [/code]
    And that works no problem for me (tried with both the thead information in the page, and an empty table tag). I've also tried it with the "oMatrix1.fnSetColumnVis(0,0);" line enabled, and this sort of works (because oMatrix1 doesn't exist in the context of fnDrawCallback on the first occasion you need to call it just after the init, and then use a check to see if the init is complete in future calls to the draw function).

    If you could detail exactly what steps you take to cause the problem to occur that would be most useful. Also if you could try it with the jEditable stuff removed, like I've done above, just to see if that might effect it, that would me most useful. Also, I can't remember, but if you have a link to show what you are seeing here, that would be really useful for debugging this.

    Regards,
    Allan
  • allanallan Posts: 63,498Questions: 1Answers: 10,470 Site admin
    Hello again,

    I've just done a bit of work to address some of the short comings of the abilities of 1.5.2 to cope with the number of columns changing, along with bStateSave - it would be great if you were willing to give this development version a go to see if it will help fix the problems you are facing. If you drop me a mail using http://datatables.net/contact I'll send you the development version.

    Regards,
    Allan
This discussion has been closed.