sDefaultContent not used in array of objects if intermediate property does not exist
sDefaultContent not used in array of objects if intermediate property does not exist
ABC
Posts: 4Questions: 0Answers: 0
I am passing an array of objects to a datatable and would like to define a column as, for example, "attr1.attr2.attr3"
Further, not all objects are expected to have a value for attr1.attr2.
So I also provide an sDefaultContent parameter.
However the function _fnGetObjectDataFn expects the entire path attr1.attr2.attr3 to be traversable. If attr1.attr2 is "undefined" then an exception will be thrown.
Instead could I suggest that _fnGetObjectDataFn should just return undefined?
A possible patch is
[code]
--- jquery.dataTables.js 2011-10-05 15:04:54.000000000 +1300
+++ local-jquery.dataTables.js 2011-10-05 15:01:38.000000000 +1300
@@ -6743,23 +6743,29 @@
if ( a.length == 2 )
{
return function (data) {
- return data[ a[0] ][ a[1] ];
+ try {return data[ a[0] ][ a[1] ];}
+ catch(e) {return undefined;}
};
}
else if ( a.length == 3 )
{
return function (data) {
- return data[ a[0] ][ a[1] ][ a[2] ];
+ try {return data[ a[0] ][ a[1] ][ a[2] ];}
+ catch(e) {return undefined;}
};
}
else
{
return function (data) {
+ try
+ {
for ( var i=0, iLen=a.length ; i
Further, not all objects are expected to have a value for attr1.attr2.
So I also provide an sDefaultContent parameter.
However the function _fnGetObjectDataFn expects the entire path attr1.attr2.attr3 to be traversable. If attr1.attr2 is "undefined" then an exception will be thrown.
Instead could I suggest that _fnGetObjectDataFn should just return undefined?
A possible patch is
[code]
--- jquery.dataTables.js 2011-10-05 15:04:54.000000000 +1300
+++ local-jquery.dataTables.js 2011-10-05 15:01:38.000000000 +1300
@@ -6743,23 +6743,29 @@
if ( a.length == 2 )
{
return function (data) {
- return data[ a[0] ][ a[1] ];
+ try {return data[ a[0] ][ a[1] ];}
+ catch(e) {return undefined;}
};
}
else if ( a.length == 3 )
{
return function (data) {
- return data[ a[0] ][ a[1] ][ a[2] ];
+ try {return data[ a[0] ][ a[1] ][ a[2] ];}
+ catch(e) {return undefined;}
};
}
else
{
return function (data) {
+ try
+ {
for ( var i=0, iLen=a.length ; i
This discussion has been closed.
Replies
Thanks for the suggestion!
Allan
Allan: Firstly, thank you very much for all the hard work you've obviously put in to this project. I rarely sign up for forums, but I had to do so to pass on my thanks.
ABC: Thanks for the great post - thankfully I spotted your comments describing the exact problem I've just myself run into, so I may I cast my vote for this in the next version of DataTables too.
Thanks again Allan and the community for all the hard work.
Fantastic to hear you like DataTables - it really means a lot to get your kind of post, so thanks!
This is certainly something that want to look at putting into the next revision (which I've just started committing a few things for). My only concern is how much overhead the try/catch block will add, particularly when dealing with large tables, since these return functions need to be as fast as possible, or risk slowing the whole table significantly, That's the first line of research for me to take!
Regards,
Allan
In the meantime I'm going to try using the above suggestion. If I have any thoughts regarding its success I'll let you know.
Thanks again folks.
How many rows / columns are you using in your table and are you using client or server-side processing?
Thanks,
Allan
Figures wise I would say around 10 columns, default 10 rows per request but regularly test with 100. Each row uses info from two types of objects minimum, and an optional third type could be held in an array with up to 10-20 items. Effectively each row is a conversation , two columns pull info from one object containing info about the creator, one with info about the project, and the final object type is a list of emails, so could have a variable number of emails and responses. These emails are to be displayed in the drill down manner.
When this is in more of a finished state I can try and provide some more accurate details, if it would help.
Regards,
Allan
I wonder if you would consider the following slightly different patch for incorporation into 1.9? It avoids the weight of exception handling by checking explicitly for undefined as it traverses the attribute path.
(Apologies for the whitespace mismatch ... I'm not using tabs)
[code]
if ( a.length == 2 )
{
return function (data) {
- return data[ a[0] ][ a[1] ];
+ // traverse the first attribute and check it was defined
+ var data = data[ a[0] ];
+ if (typeof data == 'undefined') {
+ return data;
+ }
+ return data[ a[1] ];
};
}
else if ( a.length == 3 )
{
return function (data) {
- return data[ a[0] ][ a[1] ][ a[2] ];
+ // traverse the first attribute and check it was defined
+ data = data[ a[0] ];
+ if (typeof data == 'undefined') {
+ return data;
+ }
+
+ // traverse the second attribute and check it was defined
+ data = data[ a[1] ]
+ if (typeof data == 'undefined') {
+ return data;
+ }
+ return data[ a[2] ];
};
}
else
@@ -6758,6 +6774,9 @@
for ( var i=0, iLen=a.length ; i
I was actually just about to package 1.9.0, but this does seem like a good plan to add in. Let me think about it a little and I'll get back to you :-)
Allan
I've also removed the "fast lookup" functions as they don't really provide any sizeable speed benefit and they would require a little bit more code overhead.
Unit tests have also been added to make sure this stays working for all types :-)
Commit:
https://github.com/DataTables/DataTables/commit/468390c337caa62f387bc15c5bc54c0313c99093
This will be in 1.9.0 which will be released soon :-)
Regards,
Allan
It just wasn't particularly explicit ... its doing
[code]
if data is undefined:
return data # but we know that data is the same as undefined!
[/code]
I currently do this better "setting" (and "getting") by providing custom mDataProp functions rather than patching the datatables library ... but perhaps this might also be a candidate for patching in the library?
It would be in function _fnSetObjectDataFn( mSource ) and look something like:
[code]
else if ( typeof mSource === 'string' && mSource.indexOf('.') != -1 )
{
/* If there is a . in the source string then the data source is in a nested object
* we provide two 'quick' functions for the look up to speed up the most common
* operation, and a generalised one for when it is needed
*/
var a = mSource.split('.');
if ( a.length == 2 )
...
else if ( a.length == 3 )
...
else
{
return function (data, val) {
for ( var i=0, iLen=a.length-1 ; i
Oops - I missed the return data is undefined - sorry about that! At least we are on the same track!
Nice suggestion about creating child objects that don't yet exist. As before let me think about it a little bit, but it does seem like a good idea :-)
Regards,
Allan
An error is thrown ("data is null") for the following when... data is null.
[code]data = data[ a[i] ];
if ( data === undefined )
{
return undefined;
} [/code]
(Line 822 of jquery.datatables.js)
An example case would be if mDataProp is referencing a nested field that does not exist because the parent object is null.
How would I alleviate this? (sDefaultContent does not work)
Allan
The following is a test page that has the error and is using 1.9.2:
http://live.datatables.net/etacuf/edit#source
Thanks again for responding allen, apologies for not initially posting a test page (takes a while to recreate the issue :P).