ColReorder and rowCallback don't play nicely with each other
ColReorder and rowCallback don't play nicely with each other
It looks like these two features have a bad interaction. In my real application I have used the rowCallback to decorate a fixed first column in the table with some icons replacing the underlying text. As soon as I start to drag a column to reorder I see the undecorated text reappear. I also am having to add an extra draw()
call after the table initialization to get the decoration to render correctly.
I've thrown together a quick jsfiddle ( http://jsfiddle.net/d6p2b/z8meddv6/ ) that uses colReorder and a rowCallback for some trivial cell decoration (bold if over 30). This fiddle nicely replicates the reorder issue but not my problem with needing the extra draw()
.
If you run the fiddle and...
- Sort the age column descending
- Drag the age column one place to the left
- Page through the data
.. you will see the text decoration has gone whack.
Am I doing something wrong here or is there, perhaps, a missing invocation of the callback?
This question has an accepted answers - jump to answer
Answers
Hi,
Thanks for the fiddle. The issue here is the
data[3]
- specifically, the age information is no longer in that position if the columns have been reordered. If you move it one to the left, then the age information would now be indata[2]
.There are a number of ways to address this - all requiring a bit of extra code I'm afraid.
columns.createdCell
rather thanrowCallback
. That is called only once so the index will be "correct" when called. The disadvantage is that there is noupdatedCell
callback if you happen to change the data?data.age
which doesn't change). Combining that with a class name for which column to update (columns.className
) would remove the need to handle indexes entirely.If you don't need to update the data, then 3 is the best option, if you do and you can change to using objects, 4 is best option. Otherwise 1 or 2.
In general with column reordering its best to remove any dependency on indexes - it quickly gets confusing otherwise!
Allan
Thank for the quick reply, Allan. Everything you are making makes perfect sense.
I'm not sure my fiddle really captured my situation. In my real-world case the decoration is on the fixed first column. Let me see if I can adjust the fiddle to better represent my problem.
Regardless of FixedColumns, the ColReorder index issue would remain. FixedColumns shouldn't actually have any effect on that aspect.
Allan
I still think something else has to be going on. The decorated column is fixed in position 0 and the callback is defined as:
Clearly there is nothing here that depends on any column indexes.
As soon as I start to drag any column to a new position I see the original html (rowid integers from the database) in column 0 and my nice glyphicons go away. (I've replaced the contents of the .html() with just plain text. No dice until I send another .draw() )
In case this offers any clues... There is also the odd behavior on initialization I mentioned in my original post. When I initialize the table I see the callback invoked for 10 rows. The strange thing is the .click() bit worked but the .html() didn't. I still see my rowid integers. If I add a .draw() to the initialization I see the callback called another 10 times and now the .html() and .click() have worked.
As soon as I start the drag I see no calls to the callback but I lose the modified html.
I can send you a link to the live page in a private email if you'd like. I realize that my fiddle isn't good enough to communicate the situation and this reply is a whole bunch of hand-waiving. I'm rather embarrassed to be sending it as I'm asking you to help but not letting you see the the problem for yourself.
Ah! Thanks for hte link - absolutely clear now.
The issue is that you are updating the DOM (
$('td:first', row).html( ...
) - but DataTables doesn't know you've done that. So, when the column is re-ordered and DataTables invalidates its cache (reads form the document and updates the display for the new column order) the original data is redisplayed (since rowCallback doesn't get triggered here).I would suggest, rather than using rowCallback (which is going to be bad with that event anyway - go to page 2, then back to page 1 and click the icon - the click event will trigger twice because it has been added twice!), use the
columns.defaultContent
option for this column:And for the event do:
Regards,
Allan
edit - sorry, hit sumbit early!
Yes. This all makes sense. I was too focussed on where I thought the problem must be to think about the DOM / DT interaction. Of course, you are completely correct that I am stacking on click events as well.
A couple academic questions as I'm sure you solution will get the job done for me...
Is there are reason not to trigger the rowCallback on the reorder?
Any thoughts about why I needed that extra
.draw()
when I first initialize the table to get the .html() to have an impact?Thanks!
ColReorder doesn't do a draw. The draw is avoided to try and improve performance (particularly if server-side processing is used) since it isn't really needed in this case - the data is the same. The row callback is only called when the table is drawn.
Not a clue! I can't see why that would be needed I'm afraid. It certainly shouldn't be.
Allan
Thanks for the quick and friendly answers. I'm willing to be my extra
draw()
won't be needed once I follow your suggested solution.