problem with bDeferRender and jQuery selector on table

problem with bDeferRender and jQuery selector on table

doctorjwdoctorjw Posts: 12Questions: 0Answers: 0
edited March 2012 in DataTables 1.9
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

Replies

  • doctorjwdoctorjw Posts: 12Questions: 0Answers: 0
    As a part of this ... I can set bDeferRender to false and still get a big speed improvement over the way I had been rendering the table. Clearly, the issue is trying to use jquery selectors to find elements that haven't been rendered, yet. This is an interactive table, unlike all the examples I've seen that use bDeferRender ... so maybe I'm just stuck with bDeferRender = false.
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    Hi,

    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
  • doctorjwdoctorjw Posts: 12Questions: 0Answers: 0
    It makes perfect sense that with the rows not rendered, the selectors wouldn't pick up non-visible rows.

    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
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    Hi John,

    Great to hear you've got it working as you would like - thanks for the feedback!

    Allan
  • doctorjwdoctorjw Posts: 12Questions: 0Answers: 0
    I just had to come back to this, just to indicate that ... what I was doing was probably well out of the norm. I'm currently making changes to my app to use fnRender, instead of what I had been doing (using html elements as data for the table). A few hidden columns to handle some state information (original values, for example, so I can easily track changes) and I'm golden --- I can use bDeferRender and see the fabulous boost in performance that was expected. As for the checkbox state ... it's much easier to just track the true/false values in the table data than try to parse elements.

    john
  • rpkrpk Posts: 3Questions: 0Answers: 0
    I was wondering if there was any update on resolution of the root cause?
    [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?
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    Can you post a link to an example page which shows the problem so I can investigate fully please?

    Thanks,
    Allan
  • rpkrpk Posts: 3Questions: 0Answers: 0
    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).
  • allanallan Posts: 63,498Questions: 1Answers: 10,471 Site admin
    That's superb - thanks for the example.

    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
  • rpkrpk Posts: 3Questions: 0Answers: 0
    Thanks for the quick fix!

    Integrated, tested, and pushed to production, everything worked as far as I can tell.
  • jrm213jrm213 Posts: 1Questions: 0Answers: 0
    Thanks! This was driving me nuts (TypeError a is null), I was using 1.9.1 and upgraded to 1.9.4 and the problem is solved!
  • rlatiganorlatigano Posts: 7Questions: 0Answers: 0
    edited November 2012
    hi, I here a problem with pagination when I Used jquery.datatables.editable..js. makeeditable not work on this.
    in datable configuration I using bDeferRender = true. if set up false this configuration makeeditable is very slowly, on IE8 and get error script broken.
This discussion has been closed.