No context to columns.render function?
No context to columns.render function?
arobthearab
Posts: 6Questions: 1Answers: 0
Specifying a column rendering function, the function receives expected parameters ( cell data, type, row data, metadata ) but "this" is undefined. Is there some reason this is not or should not be the API for the affected table?
This question has an accepted answers - jump to answer
This discussion has been closed.
Answers
A couple of reasons combined which mean that it isn't yet:
table.cell().data(...)
in the renderer would lead to an infinite loop.I'm open to the idea, I want to expose the API as much as possible, but I'm not sure I see enough benefits to do so here. What is the use case?
Allan
It's probably naivete on my part, but I attach my own object to the table element, a la:
$(selector).data("table", tableObject)
Note this is NOT a DataTable object, it is my own class Table. Based on information in my tableObject, my rendering function generates different HTML to go into the table in response to a "display" render type.
The issue is finding my Table object when the rendering function is called. One way to do this would be
$($(this).table().node()).data("table")
But because this is not defined, I can't do that. The way I am doing it now is:
$(metaData.settings.nTable).data("table")
But this is an ugly, internals-specific kludge.
And note this object must persist across JS scripts that do not share the same context--so a global variable, which would have to be known to the internals of my code, would be even more of a kludge.
As a neophyte, I welcome a solution that makes me look like a fool for not seeing it myself.
Do you need to access the full
tableObject
in the rendering function or could you just assign a function to the column as needed. Can you show me an example of your rendering function - it sounds like it might be doing a lot of work which would hurt performance (a rendering function should ideally be like an event handler - get in and out as quickly as possible).Allan
It's definitely hurting performance. Loading a ~350 x 20 column table takes 8-10 seconds (about 7,100 calls to the rendering function, or around 1.125-1.408ms per call).
This is the rendering class code. The handlers include things that return input fields, selects, etc. (essentially, I may be reinvented the Editor wheel). I make no claims to be idiomatic in JS, so if there are obvious performance-killers here I don't know what they are:
The performance killer here is that you are working out what rendering function to use every time
render
is called. That seems redundant unless you are expecting it to change for cells during the life time of the server? My suggestion would be to build thecolumns
array withcolumns.render
function already determined. Then it wouldn't need to either get the data from the main table node, or use the columnMap to get the rendering type - both of which will take time.Allan
Thank you Allan, that is above and beyond on your part, and something I started working on last night for the same reasons. The plan was not so much that the column renderers would change for any given application, but that this is a generic interface for many applications which might change the rendering--but even that can be dealt with beforehand and not at every render call.
But that leaves open the issue of "this" providing context in a rendering function, which is still valuable regardless of how I implement this. The
<table>
element already exists, and presumably so do the<tr>
and<td>
by the time the render function is called. Other DataTables calls do provide this context, and this is not the first time I've run into this issue to much head scratching in other more mundane contexts.Two suggestions:
2a. Consistently set "this" to the DataTables object, whatever state it is in, and the buyer beware calling things like .data().
2b. Provide a means to test the state of the DataTables object (this is probably uglier than how I breezily present it),
2c. Allow the user to store a small amount of arbitrary data in the DataTables object, such as a userContext option/API call that could return arbitrary data the user wants, and that DataTables doesn't use or care about (this is common in my other guise as an IBM mainframe/midrange developer). I understand there are many ways to do this in modern languages, but most of them are butt-ugly to my (admittedly esoteric) sensibilities.
Thank you again.
Thanks for the feedback - all sensible suggestions. What I want to do with v2 is to make the API the context of every callback - in reality I don't know if I will do that because it will break backwards compatibility (for all that it is a v2 release).
Making the
render
function have the scope of the table element similar to other callbacks is a good fallback, although it could also be argued that it should be the cell in question (although we run into issues if that doesn't exist yet).The documentation absolutely does need to state the context of the callbacks - good point.
Allan
Excellent support, above and beyond the normal and reasonable call of duty in this case. Will make me strive harder to obtain the pittance necessary to license the editor so I don't have to develop it from scratch.