problem with bDeferRender and jQuery selector on table
problem with bDeferRender and jQuery selector on table
doctorjw
Posts: 12Questions: 0Answers: 0
I am displaying a table of about 3500 rows with DataTables 1.9.0; this naturally looks like a good case for bDeferRender, as the rendering of the table was taking ~20 - 25 seconds. I made that conversion on Friday, and the table comes up much, much quicker (just a second or two). However, some functionality in my application is now broken.
In displaying a filtered subset of the table (say, 2 pages), I invoke a javascript function that I wrote to change the state of some of the cells in the table (one column is a table of checkboxes, so I created a "select all" capability) which is invoked via 'onchange'. The function basically does
[code]
var box = oTable.$(selector);
var state = box.attr("checked") == "checked";
...
[/code]
where 'selector' is the jQuery selector (in my case, something like '#store_1').
My issue is that when the table spans more than one page, and I haven't visited any pages except the first, I get an error on the jquery selector "oTable.$(selector)"; the error message returned is "a is null". Using Firebug, and placing a breakpoint on that line, I can fire a standard jquery selector ($('#store_1')) and it works just fine; only when I go through the table (oTable.$('#store_1')) does it fail.
In stepping through what is happening in the table selector, it looks like the deferred rendering is preventing the data structures necessary for the jquery selector to work. I've traced this to the following code:
[code]
/* We need to filter on the TR elements and also 'find' in their descendants
* to make the selector act like it would in a full table - so we need
* to build both results and then combine them together
*/
var jqA = $(a);
var jqTRs = jqA.filter( sSelector );
[/code]
where it bombs out on the jqA.filter(sSelector) line (line 4832 of jquery.datatables.js).
You can see this same error on the example for bDeferRender (http://datatables.net/release-datatables/examples/ajax/defer_render.html) by placing a breakpoint on the line that creates the datatable, and then stepping one line beyond it (so the table will render on the page, and you'll have access to the oTable variable in the watchpoints panel). When you hit the break, step over just enough that the oTable variable is set and the table has rendered. Set a watch on "oTable.$('.sorting_1')" to find all cells that have the sorting class turned on and you'll get the same "a is null" error, which I think is caused by the search progressing to a page other than page 1.
Help? For most of these, I could use a standard jQuery selector (not going through the table); it's inconvenient for some, though, because I'd like to find just the filtered members.
Help?
Thanks!
john
In displaying a filtered subset of the table (say, 2 pages), I invoke a javascript function that I wrote to change the state of some of the cells in the table (one column is a table of checkboxes, so I created a "select all" capability) which is invoked via 'onchange'. The function basically does
[code]
var box = oTable.$(selector);
var state = box.attr("checked") == "checked";
...
[/code]
where 'selector' is the jQuery selector (in my case, something like '#store_1').
My issue is that when the table spans more than one page, and I haven't visited any pages except the first, I get an error on the jquery selector "oTable.$(selector)"; the error message returned is "a is null". Using Firebug, and placing a breakpoint on that line, I can fire a standard jquery selector ($('#store_1')) and it works just fine; only when I go through the table (oTable.$('#store_1')) does it fail.
In stepping through what is happening in the table selector, it looks like the deferred rendering is preventing the data structures necessary for the jquery selector to work. I've traced this to the following code:
[code]
/* We need to filter on the TR elements and also 'find' in their descendants
* to make the selector act like it would in a full table - so we need
* to build both results and then combine them together
*/
var jqA = $(a);
var jqTRs = jqA.filter( sSelector );
[/code]
where it bombs out on the jqA.filter(sSelector) line (line 4832 of jquery.datatables.js).
You can see this same error on the example for bDeferRender (http://datatables.net/release-datatables/examples/ajax/defer_render.html) by placing a breakpoint on the line that creates the datatable, and then stepping one line beyond it (so the table will render on the page, and you'll have access to the oTable variable in the watchpoints panel). When you hit the break, step over just enough that the oTable variable is set and the table has rendered. Set a watch on "oTable.$('.sorting_1')" to find all cells that have the sorting class turned on and you'll get the same "a is null" error, which I think is caused by the search progressing to a page other than page 1.
Help? For most of these, I could use a standard jQuery selector (not going through the table); it's inconvenient for some, though, because I'd like to find just the filtered members.
Help?
Thanks!
john
This discussion has been closed.
Replies
Yup - deferred rendering is most certainly going to upset any selector, including the $ API method. The nodes haven't yet been created, so they can't possibly be selected - which is the whole point of how deferred rendering gets its speed boost :-). So deferred rendering + the ability to select all rows are mutually incompatible.
> I get an error on the jquery selector "oTable.$(selector)"; the error message returned is "a is null".
That's not good - it shouldn't do that. However, it will only select rows that have been rendered already (as I say, it can't possibly select rows which haven't been created). I'll look into stopping that throwing an error for the 1.9.1 release - thanks for the heads up on that!
So I guess the question is - what are you trying to do? There might be another way of achieving it.
Allan
Actually, in the end, things worked out okay. For tables where the interaction is only with the visible elements, deferred rendering works great ... with some minor tweaks to the selectors to not go through the table (for now; it wasn't required anyway, as it really was just a straight-up simple element selector). Also, I gained performance by removing a function call I was making that wasn't required (sigh ... leftover code from last week, putting drop-down filters in place; one particular case had some leftover code in place which resulted in an extra method column per row).
Currently, my tables are rendered far far faster than they were at the middle of last week, complete with text selectors, dropdown selectors, and one column of checkboxes ....
Great tool, btw! Many thanks!
john
Great to hear you've got it working as you would like - thanks for the feedback!
Allan
john
[quote]I get an error on the jquery selector "oTable.$(selector)"; the error message returned is "a is null" [/quote]
I'm currently seeing this as well, and I had thought that I saw a comment somewhere on deferred rendering that I would just be missing rows that hadn't been created yet, which is fine (I'm also using the selector to find "changes", so for any changes the row would have been created).
I'm running 1.9.1, so I guess a fix didn't make it into the update?
Thanks,
Allan
Here is a link demonstrating the problem: http://jsfiddle.net/yJWd8/
(Version using unminified datatables: http://jsfiddle.net/yJWd8/1/)
The code is taken directly from your javascript example, and then the bDeferRender property is set to true. If you click the "Break Me" button, you'll notice in firebug that it outputs [quote]TypeError: a is null[/quote] Chrome outputs [quote]Uncaught TypeError: Cannot read property 'nodeType' of null[/quote] It breaks on:
[quote]
DataTable.$ jquery.dataTables.js:4885
DataTable._ jquery.dataTables.js:4943
[/quote]
As doctorjw stated in his first post, they represent the lines:
[code]
var jqA = $(a);
var jqTRs = jqA.filter( sSelector );
[/code]
and
[code]
var aTrs = this.$( sSelector, oOpts );
[/code]
I believe the ideal behavior would be for the selectors to just omit any uninitialized rows (in this example, I would expect 10 rows of the total 12 to be dumped into the selector, as the last 2 reside on the second page and shouldn't have been created yet).
I've just committed a fix for this which can be picked up from the DataTables 1.9.2.dev nightly (available on the download page) and will be included in 1.9.2 release. The change even reduces the size of the DataTables code by 35 bytes :-).
Regards,
Allan
Integrated, tested, and pushed to production, everything worked as far as I can tell.
in datable configuration I using bDeferRender = true. if set up false this configuration makeeditable is very slowly, on IE8 and get error script broken.