aoColumnDefs, fnRender, $.getJSON combo

aoColumnDefs, fnRender, $.getJSON combo

Monkey13Monkey13 Posts: 5Questions: 0Answers: 0
edited November 2010 in General
A little at a time (I'm just getting started with datatables) I've created a working sample of a datatable which pulls JSON data from a text file (I'll eventually move it to server side processing) and displays it properly on the web page. When I try to take it to the next step by adding fnRender functions to the aoColumnDefs in the text file the table doesn't display. There is no javascript error.

Here's my working jquery followed by my working JSON text:

$(document).ready(function() {


$('#dynamic').html('');

$.getJSON("JSONTest.txt", function(data) {
$('#example').dataTable({
"aaSorting": [[0, "desc"]],
"aaData": data.aaData,
"aoColumns": data.aoColumns,
"sScrollX": "100%",
"sScrollXInner": "150%",
"bScrollCollapse": true,
"bFilter": false,
"sPaginationType": "full_numbers",
"bJQueryUI": true,
"aoColumnDefs": [
{ "sWidth": "4em", "aTargets": [0] },
{ "sWidth": "6em", "aTargets": [1] },
{ "sWidth": "15em", "aTargets": [2] },
{ "sWidth": "3em", "aTargets": [3] },
etc...
{
"fnRender": function(oObj) {
var AccountVal = oObj.aData[2];
var AccountSplit = AccountVal.split(/\|/);
var AccountLast = AccountSplit[AccountSplit.length - 1];
if (AccountLast.length > 26) {
AccountLast = AccountLast.substring(0, 25) + '...';
}
return '' + AccountLast + '';
},
"aTargets": [2]
},
{
"fnRender": function(oObj) {
return '' + oObj.aData[0] + '';
},
"aTargets": [0]
},
{
"fnRender": function(oObj) {
var NoteVal = oObj.aData[12];
if (NoteVal.length > 10) NoteVal = NoteVal.substring(0, 7) + '...';
return '' + NoteVal + '';
},
"aTargets": [12]
}
]

});
});


});



The working JSON text (contents of JSONTest.txt):


{
"sEcho": 3,
"iTotalRecords": 16,
"iTotalDisplayRecords": 10,
"aaData": [
["229889", "2010 Nov 2", "Account Value", "2010", " ", "SO", "SO", "", "$9,293,387,000.00", "F9V", "B5", "t", "blah blah bla some notes n' stuff"],
["229888", "2010 Nov 2", "Account Value", "2010", " ", " ", " ", "", "$38,000.00", "F9V", " ", "", ""],
["229887", "2010 Nov 2", "Account Value", "2010", " ", " ", " ", "", "$0.00", "F9V", " ", "", ""],
["229889", "2010 Nov 2", "Account Value", "2010", " ", "SO", "SO", "", "$9,293,387,000.00", "F9V", "B5", "t", "blah blah bla some notes n' stuff"]
],
"aoColumns": [
{ "sTitle": "ID" },
{ "sTitle": "Field1" },
{ "sTitle": "Field2" },
{ "sTitle": "Field3" },
etc...
],
"aoColumnDefs": [
{ "sWidth": "4em", "aTargets": [0] },
{ "sWidth": "6em", "aTargets": [1] },
{ "sWidth": "15em", "aTargets": [2] },
{ "sWidth": "3em", "aTargets": [3] },
etc...
]
}




Now, if I append a simple fnRender to the aoColumnDefs in the JSON text the failure occurs. It fails even if I set aoColumnDefs in my original jQuery instead of setting it from the JSON text.


"aoColumnDefs": [
{ "sWidth": "4em", "aTargets": [0] },
{ "sWidth": "6em", "aTargets": [1] },
{ "sWidth": "15em", "aTargets": [2] },
etc...
{
"fnRender": function(oObj) {
etc... }
]

Thanks for your help.

Replies

  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    Hi Monkey13,

    You have aoColumnDefs in your initilastion block of code twice, which I believe is probably the issue. I think that you want only the data.aoColumns part and not the second one which will overwrite the first, since this is not something that JavaScript objects cope with (bugs me that JavaScript engines don't throw an error about this!).

    Other than that I would say that the basic code looks good. Let us know if this works!

    Regards,
    Allan
  • Monkey13Monkey13 Posts: 5Questions: 0Answers: 0
    That makes sense and it was the first thing I tried. I think my post may have been a little confusing because I was trying to illustrate that just adding the fnRender calls in my JSON text cause it to fail wether I call aoColumnDefs from the JSON text or not. Here's my jquery code:

    [code]
    $.getJSON("JSONTest.txt", function(data) {
    $('#example').dataTable({
    "aaSorting": [[0, "desc"]],
    "aaData": data.aaData,
    "aoColumns": data.aoColumns,
    "sScrollX": "100%",
    "sScrollXInner": "150%",
    "bScrollCollapse": true,
    "bFilter": false,
    "sPaginationType": "full_numbers",
    "bJQueryUI": true,
    "aoColumnDefs": data.aoColumnDefs
    });
    });
    [/code]

    and it all works until I add fnRender to my JSON code. So if I have:

    [code]
    "aoColumnDefs": [
    { "sWidth": "4em", "aTargets": [0] },
    { "sWidth": "6em", "aTargets": [1] },
    { "sWidth": "15em", "aTargets": [2] },
    // etc...
    [code]

    that works but if I make it into:

    [code]
    "aoColumnDefs": [
    { "sWidth": "4em", "aTargets": [0] },
    { "sWidth": "6em", "aTargets": [1] },
    { "sWidth": "15em", "aTargets": [2] },
    // etc...
    "fnRender": function(oObj) {
    return '' + oObj.aData[0] + '';
    },
    "aTargets": [0]
    }
    // etc...
    [code]

    it stops working. No datatable and no error. I know the aoColumnDefs with fnRender works because if I just keep it in my jquery it works fine.
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    How very curious! I don't see anything immediately wrong with that from your explanation. Are you able to give me a link to a page which is showing this issue? ( http://datatables.net/contact if you don't want to make it public).

    Does the table render when you have the function in the aoColumnDefs string? I'm half wondering if jQuery is not allowing javascript functions in the JSON. I'll try it out...

    Allan
  • Monkey13Monkey13 Posts: 5Questions: 0Answers: 0
    Unfortunately my work environment is highly restrictive so I can't post any links. I've created some small, specific code sets that can be thrown together for testing though. I'm using them myself now to work with the bare minimum. I'll post in two posts. This one which is code that works and the next one with the minor modification that causes failure.

    This works:

    DataTables.htm
    [code]
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


    DataTables Test


    @import "css/demo_page.css";
    @import "css/demo_table_jui.css";
    @import "css/smoothness/jquery-ui-1.8.6.custom.css";












    [/code]

    DataTables.js
    [code]
    $(document).ready(function() {

    $('#dynamic').html('');

    $.getJSON("dtJSON.txt", function(data) {
    $('#example').dataTable({
    "aaSorting": [[0, "desc"]],
    "aaData": data.aaData,
    "aoColumns": data.aoColumns,
    "bScrollCollapse": true,
    "bFilter": false,
    "sPaginationType": "full_numbers",
    "bJQueryUI": true,
    "aoColumnDefs": data.aoColumnDefs
    });
    });

    });

    [/code]


    dtJSON.txt
    [code]
    {
    "sEcho": 1,
    "iTotalRecords": 6,
    "iTotalDisplayRecords": 10,
    "aaData": [
    ["229889", "2010 Nov 2", "Data1-1", "Data1-1"],
    ["229890", "2010 Nov 3", "Data1-2", "Data1-1"],
    ["229891", "2010 Nov 4", "Data1-3", "Data1-1"],
    ["229892", "2010 Nov 5", "Data1-4", "Data1-1"],
    ["229893", "2010 Nov 6", "Data1-5", "Data1-1"],
    ["229894", "2010 Nov 7", "Data1-6", "Data1-1"]
    ],
    "aoColumns": [
    { "sTitle": "ID" },
    { "sTitle": "The Date" },
    { "sTitle": "Data1" },
    { "sTitle": "Data2" }
    ],
    "aoColumnDefs": [
    { "sWidth": "4em", "aTargets": [0] },
    { "sWidth": "6em", "aTargets": [1] },
    { "sWidth": "15em", "aTargets": [2] },
    { "sWidth": "3em", "aTargets": [3] }
    ]
    }

    [/code]
  • Monkey13Monkey13 Posts: 5Questions: 0Answers: 0
    adding any fnRender in aoColumnDefs in dtJSON.txt causes failure:

    [code]
    {
    "sEcho": 1,
    "iTotalRecords": 6,
    "iTotalDisplayRecords": 10,
    "aaData": [
    ["229889", "2010 Nov 2", "Data1-1", "Data1-1"],
    ["229890", "2010 Nov 3", "Data1-2", "Data1-1"],
    ["229891", "2010 Nov 4", "Data1-3", "Data1-1"],
    ["229892", "2010 Nov 5", "Data1-4", "Data1-1"],
    ["229893", "2010 Nov 6", "Data1-5", "Data1-1"],
    ["229894", "2010 Nov 7", "Data1-6", "Data1-1"]
    ],
    "aoColumns": [
    { "sTitle": "ID" },
    { "sTitle": "The Date" },
    { "sTitle": "Data1" },
    { "sTitle": "Data2" }
    ],
    "aoColumnDefs": [
    { "sWidth": "4em", "aTargets": [0] },
    { "sWidth": "6em", "aTargets": [1] },
    { "sWidth": "15em", "aTargets": [2] },
    { "sWidth": "3em", "aTargets": [3] },
    {
    "fnRender": function(oObj) {
    return '' + oObj.aData[0] + '';
    },
    "aTargets": [0]
    }
    ]
    }
    [/code]

    Maybe it would work if I didn't have to put fnRender in aoColumnDefs but I'm still learning about DataTables and jQuery and I don't know how to do that or if it's possible.

    Hey, if you're in the US don't spend holiday time on this ok? It can wait.

    Thanks
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    Hi Monkey13,

    I'm UK based so no worries on the holiday front :-). I'm am away from my computer atm though and replying on my phone, so forgive me if this isn't a great reply!

    I'm almost certain that the issue is with the parsing of the neon by jquery. The jquery documentation nots that getJSON uses $.parseJSON, the documentation for which says "Takes a well-formed JSON string and returns the resulting JavaScript object". The problem you face is that function(){}, is not a valid json value ( http://json.org ), so I think jquery is rejecting it. To test this (I'll try it when I'm back at my computer) I would suggest using $.Ajax and set an error handler. I believe that jquery will be giving an error, but since there is no error handler for getJSON it just disappears.

    There are a couple of options to address this I believe. The first is to simply eval() the string the server returns your self, another slightly more complicated one would be you use JSONP. finally you could have the server set a flag for what function it wants the fnRender to be and then have the client side replace that string with an already available function.

    I would say that in the case above the easiest thing to do is simply have the server render the link for you and return that as part of the json. If that isn't enough then consider an eval() call.

    Regards,
    Allan
  • Monkey13Monkey13 Posts: 5Questions: 0Answers: 0
    Yes, that makes sense that a function can't be passed. Your suggestion to have the server set a flag for an already available function is my preference as I have other functions I'd like to implement as well. For code readability I'd actually prefer that over passing functions via JSON but I have no clue how to do it. An example would be much appreciated.

    Thanks
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    Hi Monkey13,

    I'll bash together an example using eval() tomorrow morning which should do the job for you (sorry I can't do it right now, probably take me until tomorrow morning on my phone!).

    Regards,
    Allan
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    edited November 2010
    Hi Monkey13,

    Sorry for the delay in getting back to you about this! Here is an example of how it might be done using eval:

    [code]
    $(document).ready(function() {
    $('#dynamic').html('');

    $.ajax( {
    "dataType": 'text',
    "type": "GET",
    "url": "dtJSON.txt",
    "success": function (dataStr) {
    var data = eval( '('+dataStr+')' );
    $('#example').dataTable({
    "aaSorting": [[0, "desc"]],
    "aaData": data.aaData,
    "aoColumns": data.aoColumns,
    "bScrollCollapse": true,
    "bFilter": false,
    "sPaginationType": "full_numbers",
    "bJQueryUI": true,
    "aoColumnDefs": data.aoColumnDefs
    });
    }
    } );
    });
    [/code]
    It would be remiss of me not to not to note that eval() should be used with caution! Generally speaking it should be avoided, although can be useful in places like this. There are security issues that should be considered when eval()ing (particularly when using data from a 3rd party!). Something to bare in mind!

    Regards,

    Allan
This discussion has been closed.