deep property reading for a data source missing nested object behavior

deep property reading for a data source missing nested object behavior

jamjon3jamjon3 Posts: 22Questions: 0Answers: 0
edited May 2011 in DataTables 1.8
This is a GREAT feature. I usually have to convert arrays of objects to arrays of arrays on the client side which is problematic with large results. However, in trying this out, I ran into some behavior I normally would catch manually before sending the array of arrays back to datatables.

Here's the scenario and a little example:
[code]
{ "sTitle": "ID","sClass": "SearchColumn","mDataProp": "defaultIdentifier.identifier","bVisible": true },
[/code]

In the JSON object, sometimes doesn't have a default identifier and looks like:
[code]
"defaultIdentifier":{},
[/code]

Then I get a message for the first and last row of the return that looks like:

DataTables warning (table id = 'searchResultTable'): Requested unknown parameter 'defaultIdentifier.identifier' from the data
source for row 0

I'm not manually serializing and de-serializing objects back and forth to JSON. I'm doing this in Java and currently using GSON but the JSON object I'm getting back exactly represents the Java objects before (de)serialization so it's an honest representation of the data. In short, I have a variable depth of objects returned in the array. Is there some setting that will treat an "undefined" references simply as an empty field?

Replies

  • allanallan Posts: 63,490Questions: 1Answers: 10,470 Site admin
    Hi jamjon3,

    I think that this is an excellent suggestion, and I've just expanded on it a little and committed it into the core - which you can now grab from the downloads page (the nightly version).

    What I've done is to add a new initialisation property for the columns: sDefaultContent. This new property allows a default value to be given for a column's data, and will be used whenever a null data source is encountered (this can be because mDataProp is set to null, or because the data source itself is null). In addition to this, when set if the mDataProp value is undefined, the default will be used instead (and no error given). If sDefaultContent is not set (default is null), and the mDataProp value is undefined, an error will be given as it currently is.

    I think an example is worth a thousand words for this one (although I think a tutorial might be suitable on the blog at some point...):

    [code]
    $('#example').dataTable( {
    "aaData": aDataSet,
    "aoColumnDefs": [
    {
    // All cells get a value of 'hello'
    sDefaultContent: "hello",
    mDataProp: null,
    aTargets: [0]
    },
    {
    // When there is no my.prop value for the data source the 'world' is shown
    sDefaultContent: "world",
    mDataProp: 'my.prop',
    aTargets: [1]
    }
    ]
    } );
    [/code]
    I think this ability to have a default value for columns will be quite useful (add, edit and delete links for example) and the ability to 'bypass' the warning you noticed falls out of it.

    Regards,
    Allan
  • jamjon3jamjon3 Posts: 22Questions: 0Answers: 0
    Absolutely amazing and thanks! I'll be testing that tomorrow (about to leave). I'll pop back in after I restore my version with the deep property reading in the morning and thank you soooooo much!

    I was experimenting with fnServerData to handle this as it's a dynamic search result that I can't go back and get pages of it so I did a .data() bind on the result and passed it through and processed it "like" I was doing AJAX again (I know, very convoluted doing the reformatting, sorting and paging... which works but still a lot of processing). I'm certainly going back to the deep property reading rather than other mechanisms I was using to handle large results (70M+) (each "row" has a hidden column with other rated combinations for the same identity I show in details). I originally was doing a JSON.stringify on that last column which, itself, was an array of arrays. I'll see how I can handle this after getting the deep property reading working on the outer table and THANK YOU!!!!!!!
  • jamjon3jamjon3 Posts: 22Questions: 0Answers: 0
    This is working now. I do have something I post as a new item regarding "fnRender" (aka: in addition to outputing a string, also a JQuery object). SUPER FANTASTIC plugin you have!!! Here's a snipit of what I have so far (if of any use to anybody):

    [code]
    searchResultDataTable = (self.searchResultDataTable = searchResultTable.width('100%').dataTable({
    "aaSorting": [[23,"desc"],[ 2, "asc" ],[ 22, "asc" ],[ 5, "asc" ],[ 3, "asc" ],[ 4, "asc" ],[ 9, "asc" ],[ 10, "asc" ]],
    "aoColumns": [
    { "bSortable": false,"sClass": "SearchColumnDetails","bVisible": true,"mDataProp": "null", "fnRender":
    function(oObj) {
    return "";
    }
    },
    { "sTitle": "USFID ","sClass": "SearchColumn","mDataProp": "defaultIdentifier.identifier","sDefaultContent":"","bVisible": true },
    [/code]

    I had to cut the code out as it was too long with the fnRowCallback....

    Also, I see that in the "fnRender", I refer to data in the object row as something like: oObj.aData.defaultIdentifier.identifier rather than oObj.aData[1] (That's SUPER USEFUL and I'm doing so).
  • allanallan Posts: 63,490Questions: 1Answers: 10,470 Site admin
    Nice one - good to hear that is doing the job for you :-)

    Allan
  • jiserukjiseruk Posts: 0Questions: 0Answers: 0
    Hi! I have an issue with sDefaultContent. It doesn't work when I have an array object than can be null as a value of e key in my json.
    I show you the example:
    "aoColumns": [
    {},{},....
    { "mDataProp": "bar.0.foo", "sDefaultContent": "uuuf"}
    ]
    And my JSON has the form:
    {
    ....,
    bar: [{"foo":"blabla"},{},....]

    }

    But when I load the page I get when "bar" has no value:
    Uncaught TypeError: Cannot read property 'foo' of undefined

    Can you help me with this issue? Am I doing something wrong?
    Thanks!!
  • allanallan Posts: 63,490Questions: 1Answers: 10,470 Site admin
    I don't see anything obviously wrong - can you give us a link to your page so I can see it in action please?

    Thanks,
    Allan
  • shanimalshanimal Posts: 6Questions: 0Answers: 0
    edited December 2011
    sDefaultContent seems to work whenever there is no value specified for mDataProp. But when a property specified by mDataProp is not present in a row I get an error.

    For example: The web-service I am using removes data nodes when a value is null. So row 47 might be {name:"Foo",startDate:302948897012} and row 48 might be {name:"Bar"}. When datatables encounters record 48, I get:

    "DataTables warning (table id = 'table'): Requested unknown parameter 'startDate' from the data source for row 48"

    Does it make sense that sDefaultContent could fill in for this case as well?

    EDIT: Sorry, it already works. A conditional in my code was preventing the property from being added to the column definition. Thanks!
  • hrobayohrobayo Posts: 1Questions: 0Answers: 0
    Hi, I have the same problen, in the server if I have a nested object like this:

    {"contribuyentes":[{"clase":null,"id":1500,"info":{"clausurable":"NO","fechaVerificacion":"31-07-2012","ubicado":"NO"},"prelacion":null,"razonSocial":"ROBAYO DUTAN VICTOR GONZA","ruc":"0100845957001"}],"iTotalDisplayRecords":1,"iTotalRecords":1,"sEcho":"2"}

    and the definition of aoColumns is:

    "aoColumns": [
    { "mDataProp": "id"},
    { "mDataProp": "razonSocial" },
    { "mDataProp": "ruc" },
    { "mDataProp": "info.ubicado" },
    { "mDataProp": "info.clausurable" },
    { "mDataProp": "info.fechaVerificacion" },
    { "mDataProp": "clase.nombre", "sDefaultContent": "" },
    { "mDataProp": "prelacion.nombre", "sDefaultContent": "" }
    ]

    don´t care about sDefaultContent is set I have an error in line 822 (jquery.dataTables-1.9.2.js) data is null, to fix this I make this change in _fnSetObjectDataFn function, adding a return line when data is null so the recursive function ends.

    /* If there is a . in the source string then the data source is in a
    * nested object so we loop over the data for each level to get the next
    * level down. On each loop we test for undefined, and if found immediatly
    * return. This allows entire objects to be missing and sDefaultContent to
    * be used if defined, rather than throwing an error
    */
    var a = mSource.split('.');
    return function (data, type) {
    for ( var i=0, iLen=a.length ; i
  • allanallan Posts: 63,490Questions: 1Answers: 10,470 Site admin
    Can you link me to a test case page (perhaps with http://live.datatables.net ) which shows the issue you are having with just plain DataTables?

    Allan
This discussion has been closed.